Bug
[В начало]
Ошибка # 118
Показать/спрятать трассу ошибок Error trace
/*Is true unsafe:*/ /*Number of usage points:2*/ /*Number of usages :2*/ /*Two examples:*/ /*_____________________*/ /*mutex_lock(char *"_hal_mutex_of_wcn36xx")[1]*/ /*Failure in refinement*/ { return ; } { /*_____________________*/ 180 struct ieee80211_tx_control *ldvarg18; 181 enum ieee80211_ampdu_mlme_action ldvarg11; 182 struct ieee80211_vif *ldvarg20; 183 unsigned long long ldvarg7; 184 struct ieee80211_bss_conf *ldvarg23; 185 struct ieee80211_vif *ldvarg3; 186 unsigned char ldvarg12; 187 unsigned int *ldvarg8; 188 struct ieee80211_sta *ldvarg1; 189 struct ieee80211_vif *ldvarg13; 190 struct ieee80211_key_conf *ldvarg29; 191 u16 *ldvarg10; 192 unsigned int ldvarg9; 193 struct ieee80211_vif *ldvarg24; 194 enum set_key_cmd ldvarg27; 195 struct ieee80211_vif *ldvarg26; 196 struct ieee80211_vif *ldvarg0; 197 u8 *ldvarg5; 198 unsigned int ldvarg30; 199 unsigned short ldvarg16; 200 struct ieee80211_vif *ldvarg6; 201 struct ieee80211_sta *ldvarg15; 202 struct ieee80211_vif *ldvarg21; 203 unsigned int ldvarg25; 204 struct sk_buff *ldvarg17; 205 unsigned int ldvarg4; 206 _Bool ldvarg14; 207 struct cfg80211_wowlan *ldvarg22; 208 struct ieee80211_sta *ldvarg19; 209 struct ieee80211_sta *ldvarg28; 210 struct ieee80211_vif *ldvarg2; 211 int tmp; 212 int tmp___0; 213 int tmp___1; 214 int tmp___2; 215 int tmp___3; 216 int tmp___4; 217 int tmp___5; 218 int tmp___6; 219 int tmp___7; 220 int tmp___8; 179 ldv_initialize() { /* Function call is skipped due to function is undefined */} 213 ldv_state_variable_6 = 0; 214 ldv_state_variable_4 = 0; 216 ldv_state_variable_1 = 1; 217 ref_cnt = 0; 218 ldv_state_variable_0 = 1; 219 ldv_state_variable_3 = 0; 221 ldv_state_variable_2 = 1; 222 ldv_state_variable_5 = 0; 223 ldv_55442:; 224 tmp = __VERIFIER_nondet_int() { /* Function call is skipped due to function is undefined */} 224 switch (tmp); 229 tmp___0 = __VERIFIER_nondet_int() { /* Function call is skipped due to function is undefined */} 229 switch (tmp___0); { 793 struct wcn36xx *wcn; 794 struct wcn36xx_vif *vif_priv; 795 struct wcn36xx_sta *sta_priv; 796 struct lock_class_key __key; 794 struct wcn36xx *__CPAchecker_TMP_0 = (struct wcn36xx *)(hw->priv); 794 wcn = __CPAchecker_TMP_0; 795 vif_priv = (struct wcn36xx_vif *)(&(vif->drv_priv)); 796 sta_priv = (struct wcn36xx_sta *)(&(sta->drv_priv)); { 291 return &(lock->__annonCompField8.rlock);; } 800 __raw_spin_lock_init(&(sta_priv->ampdu_lock.__annonCompField8.rlock), "&(&sta_priv->ampdu_lock)->rlock", &__key) { /* Function call is skipped due to function is undefined */} 801 vif_priv->sta = sta_priv; 802 sta_priv->vif = vif_priv; 807 unsigned int __CPAchecker_TMP_1 = (unsigned int)(vif->type); { 520 int i; 521 int size; 522 u16 *rates_table; 523 struct wcn36xx_sta *sta_priv; 524 unsigned int rates; 523 sta_priv = (struct wcn36xx_sta *)(&(sta->drv_priv)); 524 rates = (sta->supp_rates)[(unsigned int)band]; 526 __memset((void *)(&(sta_priv->supported_rates)), 0, 58UL) { /* Function call is skipped due to function is undefined */} 528 sta_priv->supported_rates.op_rate_mode = 6; 530 size = 4; 531 rates_table = (u16 *)(&(sta_priv->supported_rates.dsss_rates)); 541 size = 8; 542 rates_table = (u16 *)(&(sta_priv->supported_rates.ofdm_rates)); 543 i = 0; 543 goto ldv_55191; 545 goto ldv_55190; 544 ldv_55190:; 545 *(rates_table + ((unsigned long)i)) = (wcn_5ghz_rates[i]).hw_value; 546 rates = rates >> 1; 543 i = i + 1; 544 ldv_55191:; 545 goto ldv_55190; 544 ldv_55190:; 545 *(rates_table + ((unsigned long)i)) = (wcn_5ghz_rates[i]).hw_value; 546 rates = rates >> 1; 543 i = i + 1; 544 ldv_55191:; 553 __memcpy((void *)(&(sta_priv->supported_rates.supported_mcs_set)), (const void *)(&(sta->ht_cap.mcs.rx_mask)), 10UL) { /* Function call is skipped due to function is undefined */} } 809 sta_priv->aid = sta->aid; { 1021 struct wcn36xx_hal_config_sta_req_msg msg; 1022 struct wcn36xx_hal_config_sta_params *sta_params; 1023 int ret; 1024 _Bool tmp; 1025 int tmp___0; 1024 ret = 0; { /*Change states for locks mutex_lock(char *"_hal_mutex_of_wcn36xx")*/ 666 ldv_mutex_lock(ldv_func_arg1, (char *)"_hal_mutex_of_wcn36xx") { /* Function call is skipped due to function is undefined */} } 1027 __memset((void *)(&msg), 0, 113UL) { /* Function call is skipped due to function is undefined */} 1027 msg.header.msg_type = 12U; 1027 msg.header.msg_version = 0U; 1027 msg.header.len = 113U; 1029 sta_params = &(msg.sta_params); { 192 struct wcn36xx_vif *priv_vif; 193 struct wcn36xx_sta *priv_sta; 194 priv_vif = (struct wcn36xx_vif *)(&(vif->drv_priv)); 195 priv_sta = (struct wcn36xx_sta *)0; 196 unsigned int __CPAchecker_TMP_0 = (unsigned int)(vif->type); 196 unsigned int __CPAchecker_TMP_1 = (unsigned int)(vif->type); 196 unsigned int __CPAchecker_TMP_2 = (unsigned int)(vif->type); 202 sta_params->type = 0U; 203 sta_params->sta_index = 1U; 206 sta_params->listen_interval = wcn->hw->conf.listen_interval; 213 unsigned int __CPAchecker_TMP_3 = (unsigned int)(vif->type); 216 __memcpy((void *)(&(sta_params->bssid)), (const void *)(&(vif->addr)), 6UL) { /* Function call is skipped due to function is undefined */} 218 u32 __CPAchecker_TMP_4 = (u32 )(priv_vif->encrypt_type); 218 sta_params->encrypt_type = __CPAchecker_TMP_4; 219 sta_params->short_preamble_supported = 1U; 221 sta_params->rifs_mode = 0U; 222 sta_params->rmf = 0U; 223 sta_params->action = 0U; 224 sta_params->uapsd = 0U; 225 sta_params->mimo_ps = 0; 226 sta_params->max_ampdu_duration = 0U; 227 sta_params->bssid_index = priv_vif->bss_index; 228 sta_params->p2p = 0U; { 560 u16 ofdm_rates[8U]; 561 u16 dsss_rates[4U]; 560 ofdm_rates[0] = 12U; 560 ofdm_rates[1] = 18U; 560 ofdm_rates[2] = 24U; 560 ofdm_rates[3] = 36U; 560 ofdm_rates[4] = 48U; 560 ofdm_rates[5] = 72U; 560 ofdm_rates[6] = 96U; 560 ofdm_rates[7] = 108U; 570 dsss_rates[0] = 130U; 570 dsss_rates[1] = 132U; 570 dsss_rates[2] = 139U; 570 dsss_rates[3] = 150U; 577 rates->op_rate_mode = 6; 578 __memcpy((void *)(&(rates->dsss_rates)), (const void *)(&dsss_rates), 8UL) { /* Function call is skipped due to function is undefined */} 580 __memcpy((void *)(&(rates->ofdm_rates)), (const void *)(&ofdm_rates), 16UL) { /* Function call is skipped due to function is undefined */} 582 (rates->supported_mcs_set)[0] = 255U; } { } 176 sta_params->ht_capable = 1U; 177 sta_params->tx_channel_width_set = 1U; 178 sta_params->lsig_txop_protection = 1U; 179 sta_params->max_ampdu_size = 3U; 180 sta_params->max_ampdu_density = 5U; 181 sta_params->max_amsdu_size = 0U; 182 sta_params->sgi_20Mhz = 1U; 183 sta_params->sgi_40mhz = 1U; 184 sta_params->green_field_capable = 1U; 185 sta_params->delayed_ba_support = 0U; 186 sta_params->dsss_cck_mode_40mhz = 1U; } { 253 int __CPAchecker_TMP_0; 253 int __CPAchecker_TMP_1 = (int)(wcn->fw_major); __CPAchecker_TMP_0 = 0; } 1033 tmp___0 = 1; { 1000 struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; 1001 struct wcn36xx_hal_config_sta_params_v1 *sta; 1002 int tmp; 1002 sta = &(msg_body.sta_params); 1004 __memset((void *)(&msg_body), 0, 114UL) { /* Function call is skipped due to function is undefined */} 1004 msg_body.header.msg_type = 12U; 1004 msg_body.header.msg_version = 0U; 1004 msg_body.header.len = 114U; { 948 __memcpy((void *)(&(v1->bssid)), (const void *)(&(orig->bssid)), 6UL) { /* Function call is skipped due to function is undefined */} 949 __memcpy((void *)(&(v1->mac)), (const void *)(&(orig->mac)), 6UL) { /* Function call is skipped due to function is undefined */} 950 v1->aid = orig->aid; 951 v1->type = orig->type; 952 v1->listen_interval = orig->listen_interval; 953 v1->ht_capable = orig->ht_capable; 955 v1->max_ampdu_size = orig->max_ampdu_size; 956 v1->max_ampdu_density = orig->max_ampdu_density; 957 v1->sgi_40mhz = orig->sgi_40mhz; 958 v1->sgi_20Mhz = orig->sgi_20Mhz; 960 __memcpy((void *)(&(v1->supported_rates)), (const void *)(&(orig->supported_rates)), 58UL) { /* Function call is skipped due to function is undefined */} 962 v1->sta_index = orig->sta_index; } 1009 void *__CPAchecker_TMP_0 = (void *)(wcn->hal_buf); 1009 __memset(__CPAchecker_TMP_0, 0, (size_t )(msg_body.header.len)) { /* Function call is skipped due to function is undefined */} 1009 void *__CPAchecker_TMP_1 = (void *)(wcn->hal_buf); 1009 __memcpy(__CPAchecker_TMP_1, (const void *)(&msg_body), 114UL) { /* Function call is skipped due to function is undefined */} { } 250 int ret; 251 unsigned long start; 252 unsigned long tmp; 253 unsigned long tmp___0; 254 unsigned int tmp___1; 250 ret = 0; { 75 struct lock_class_key __key; 75 x->done = 0U; 76 __init_waitqueue_head(&(x->wait), "&x->wait", &__key) { /* Function call is skipped due to function is undefined */} 78 return ;; } 255 start = jiffies; 256 char *__CPAchecker_TMP_1 = (char *)(wcn->hal_buf); 256 ret = (*(wcn->ctrl_ops->tx))(__CPAchecker_TMP_1, len); { 356 unsigned long tmp___0; 361 tmp___0 = __msecs_to_jiffies(m) { /* Function call is skipped due to function is undefined */} 361 return tmp___0;; } 261 tmp___0 = wait_for_completion_timeout(&(wcn->hal_rsp_compl), tmp) { /* Function call is skipped due to function is undefined */} 272 out:; } 1050 void *__CPAchecker_TMP_7 = (void *)(wcn->hal_buf); { 968 struct wcn36xx_hal_config_sta_rsp_msg *rsp; 969 struct config_sta_rsp_params *params; 970 struct wcn36xx_sta *sta_priv; 972 sta_priv = (struct wcn36xx_sta *)(&(sta->drv_priv)); 977 rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf; 978 params = &(rsp->params); 986 sta_priv->sta_index = params->sta_index; 987 sta_priv->dpu_desc_index = params->dpu_index; 988 sta_priv->ucast_dpu_sign = params->uc_ucast_sig; return ;; } return ;; } return ;; } return ;; }/*Without locks*/ { return ; } { 180 struct ieee80211_tx_control *ldvarg18; 181 enum ieee80211_ampdu_mlme_action ldvarg11; 182 struct ieee80211_vif *ldvarg20; 183 unsigned long long ldvarg7; 184 struct ieee80211_bss_conf *ldvarg23; 185 struct ieee80211_vif *ldvarg3; 186 unsigned char ldvarg12; 187 unsigned int *ldvarg8; 188 struct ieee80211_sta *ldvarg1; 189 struct ieee80211_vif *ldvarg13; 190 struct ieee80211_key_conf *ldvarg29; 191 u16 *ldvarg10; 192 unsigned int ldvarg9; 193 struct ieee80211_vif *ldvarg24; 194 enum set_key_cmd ldvarg27; 195 struct ieee80211_vif *ldvarg26; 196 struct ieee80211_vif *ldvarg0; 197 u8 *ldvarg5; 198 unsigned int ldvarg30; 199 unsigned short ldvarg16; 200 struct ieee80211_vif *ldvarg6; 201 struct ieee80211_sta *ldvarg15; 202 struct ieee80211_vif *ldvarg21; 203 unsigned int ldvarg25; 204 struct sk_buff *ldvarg17; 205 unsigned int ldvarg4; 206 _Bool ldvarg14; 207 struct cfg80211_wowlan *ldvarg22; 208 struct ieee80211_sta *ldvarg19; 209 struct ieee80211_sta *ldvarg28; 210 struct ieee80211_vif *ldvarg2; 211 int tmp; 212 int tmp___0; 213 int tmp___1; 214 int tmp___2; 215 int tmp___3; 216 int tmp___4; 217 int tmp___5; 218 int tmp___6; 219 int tmp___7; 220 int tmp___8; 179 ldv_initialize() { /* Function call is skipped due to function is undefined */} 213 ldv_state_variable_6 = 0; 214 ldv_state_variable_4 = 0; 216 ldv_state_variable_1 = 1; 217 ref_cnt = 0; 218 ldv_state_variable_0 = 1; 219 ldv_state_variable_3 = 0; 221 ldv_state_variable_2 = 1; 222 ldv_state_variable_5 = 0; 223 ldv_55442:; 224 tmp = __VERIFIER_nondet_int() { /* Function call is skipped due to function is undefined */} 224 switch (tmp); 229 tmp___0 = __VERIFIER_nondet_int() { /* Function call is skipped due to function is undefined */} 229 switch (tmp___0); 388 -wcn36xx_ampdu_action(wcn36xx_ops_group0, ldvarg13, ldvarg11, ldvarg15, (int)ldvarg16, ldvarg10, (int)ldvarg12, (int)ldvarg14) { 862 struct wcn36xx *wcn; 863 struct wcn36xx_sta *sta_priv; 864 unsigned char tmp; 865 unsigned char tmp___0; 866 unsigned char tmp___1; 867 unsigned char tmp___2; 864 struct wcn36xx *__CPAchecker_TMP_0 = (struct wcn36xx *)(hw->priv); 864 wcn = __CPAchecker_TMP_0; 865 sta_priv = (struct wcn36xx_sta *)0; 870 sta_priv = (struct wcn36xx_sta *)(&(sta->drv_priv)); 872 switch ((unsigned int)action); { /*Change states for locks spin_lock(char *"_ampdu_lock_of_wcn36xx_sta")*/ 993 ldv_spin_lock(lock, (char *)"_ampdu_lock_of_wcn36xx_sta") { /* Function call is skipped due to function is undefined */} } 892 (sta_priv->ampdu_state)[(int)tid] = 3; { /*Change states for locks spin_lock(char *"_ampdu_lock_of_wcn36xx_sta")*/ 999 ldv_spin_unlock(lock, (char *)"_ampdu_lock_of_wcn36xx_sta") { /* Function call is skipped due to function is undefined */} } { 176 int __CPAchecker_TMP_1; 176 unsigned int __CPAchecker_TMP_2 = (unsigned int)(vif->type); 176 __CPAchecker_TMP_1 = sta_priv->sta_index; return ;; } return ;; } return ;; } | Source code
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/debugfs.h>
20 #include <linux/uaccess.h>
21 #include "wcn36xx.h"
22 #include "debug.h"
23 #include "pmc.h"
24
25 #ifdef CONFIG_WCN36XX_DEBUGFS
26
27 static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf,
28 size_t count, loff_t *ppos)
29 {
30 struct wcn36xx *wcn = file->private_data;
31 struct wcn36xx_vif *vif_priv = NULL;
32 struct ieee80211_vif *vif = NULL;
33 char buf[3];
34
35 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
36 vif = container_of((void *)vif_priv,
37 struct ieee80211_vif,
38 drv_priv);
39 if (NL80211_IFTYPE_STATION == vif->type) {
40 if (vif_priv->pw_state == WCN36XX_BMPS)
41 buf[0] = '1';
42 else
43 buf[0] = '0';
44 break;
45 }
46 }
47 buf[1] = '\n';
48 buf[2] = 0x00;
49
50 return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
51 }
52
53 static ssize_t write_file_bool_bmps(struct file *file,
54 const char __user *user_buf,
55 size_t count, loff_t *ppos)
56 {
57 struct wcn36xx *wcn = file->private_data;
58 struct wcn36xx_vif *vif_priv = NULL;
59 struct ieee80211_vif *vif = NULL;
60
61 char buf[32];
62 int buf_size;
63
64 buf_size = min(count, (sizeof(buf)-1));
65 if (copy_from_user(buf, user_buf, buf_size))
66 return -EFAULT;
67
68 switch (buf[0]) {
69 case 'y':
70 case 'Y':
71 case '1':
72 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
73 vif = container_of((void *)vif_priv,
74 struct ieee80211_vif,
75 drv_priv);
76 if (NL80211_IFTYPE_STATION == vif->type) {
77 wcn36xx_enable_keep_alive_null_packet(wcn, vif);
78 wcn36xx_pmc_enter_bmps_state(wcn, vif);
79 }
80 }
81 break;
82 case 'n':
83 case 'N':
84 case '0':
85 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
86 vif = container_of((void *)vif_priv,
87 struct ieee80211_vif,
88 drv_priv);
89 if (NL80211_IFTYPE_STATION == vif->type)
90 wcn36xx_pmc_exit_bmps_state(wcn, vif);
91 }
92 break;
93 }
94
95 return count;
96 }
97
98 static const struct file_operations fops_wcn36xx_bmps = {
99 .open = simple_open,
100 .read = read_file_bool_bmps,
101 .write = write_file_bool_bmps,
102 };
103
104 static ssize_t write_file_dump(struct file *file,
105 const char __user *user_buf,
106 size_t count, loff_t *ppos)
107 {
108 struct wcn36xx *wcn = file->private_data;
109 char buf[255], *tmp;
110 int buf_size;
111 u32 arg[WCN36xx_MAX_DUMP_ARGS];
112 int i;
113
114 memset(buf, 0, sizeof(buf));
115 memset(arg, 0, sizeof(arg));
116
117 buf_size = min(count, (sizeof(buf) - 1));
118 if (copy_from_user(buf, user_buf, buf_size))
119 return -EFAULT;
120
121 tmp = buf;
122
123 for (i = 0; i < WCN36xx_MAX_DUMP_ARGS; i++) {
124 char *begin;
125 begin = strsep(&tmp, " ");
126 if (begin == NULL)
127 break;
128
129 if (kstrtou32(begin, 0, &arg[i]) != 0)
130 break;
131 }
132
133 wcn36xx_info("DUMP args is %d %d %d %d %d\n", arg[0], arg[1], arg[2],
134 arg[3], arg[4]);
135 wcn36xx_smd_dump_cmd_req(wcn, arg[0], arg[1], arg[2], arg[3], arg[4]);
136
137 return count;
138 }
139
140 static const struct file_operations fops_wcn36xx_dump = {
141 .open = simple_open,
142 .write = write_file_dump,
143 };
144
145 #define ADD_FILE(name, mode, fop, priv_data) \
146 do { \
147 struct dentry *d; \
148 d = debugfs_create_file(__stringify(name), \
149 mode, dfs->rootdir, \
150 priv_data, fop); \
151 dfs->file_##name.dentry = d; \
152 if (IS_ERR(d)) { \
153 wcn36xx_warn("Create the debugfs entry failed");\
154 dfs->file_##name.dentry = NULL; \
155 } \
156 } while (0)
157
158
159 void wcn36xx_debugfs_init(struct wcn36xx *wcn)
160 {
161 struct wcn36xx_dfs_entry *dfs = &wcn->dfs;
162
163 dfs->rootdir = debugfs_create_dir(KBUILD_MODNAME,
164 wcn->hw->wiphy->debugfsdir);
165 if (IS_ERR(dfs->rootdir)) {
166 wcn36xx_warn("Create the debugfs failed\n");
167 dfs->rootdir = NULL;
168 }
169
170 ADD_FILE(bmps_switcher, S_IRUSR | S_IWUSR,
171 &fops_wcn36xx_bmps, wcn);
172 ADD_FILE(dump, S_IWUSR, &fops_wcn36xx_dump, wcn);
173 }
174
175 void wcn36xx_debugfs_exit(struct wcn36xx *wcn)
176 {
177 struct wcn36xx_dfs_entry *dfs = &wcn->dfs;
178 debugfs_remove_recursive(dfs->rootdir);
179 }
180
181 #endif /* CONFIG_WCN36XX_DEBUGFS */ 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 /* DXE - DMA transfer engine
18 * we have 2 channels(High prio and Low prio) for TX and 2 channels for RX.
19 * through low channels data packets are transfered
20 * through high channels managment packets are transfered
21 */
22
23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25 #include <linux/interrupt.h>
26 #include "wcn36xx.h"
27 #include "txrx.h"
28
29 void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low)
30 {
31 struct wcn36xx_dxe_ch *ch = is_low ?
32 &wcn->dxe_tx_l_ch :
33 &wcn->dxe_tx_h_ch;
34
35 return ch->head_blk_ctl->bd_cpu_addr;
36 }
37
38 static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
39 {
40 wcn36xx_dbg(WCN36XX_DBG_DXE,
41 "wcn36xx_dxe_write_register: addr=%x, data=%x\n",
42 addr, data);
43
44 writel(data, wcn->mmio + addr);
45 }
46
47 #define wcn36xx_dxe_write_register_x(wcn, reg, reg_data) \
48 do { \
49 if (wcn->chip_version == WCN36XX_CHIP_3680) \
50 wcn36xx_dxe_write_register(wcn, reg ## _3680, reg_data); \
51 else \
52 wcn36xx_dxe_write_register(wcn, reg ## _3660, reg_data); \
53 } while (0) \
54
55 static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
56 {
57 *data = readl(wcn->mmio + addr);
58
59 wcn36xx_dbg(WCN36XX_DBG_DXE,
60 "wcn36xx_dxe_read_register: addr=%x, data=%x\n",
61 addr, *data);
62 }
63
64 static void wcn36xx_dxe_free_ctl_block(struct wcn36xx_dxe_ch *ch)
65 {
66 struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl, *next;
67 int i;
68
69 for (i = 0; i < ch->desc_num && ctl; i++) {
70 next = ctl->next;
71 kfree(ctl);
72 ctl = next;
73 }
74 }
75
76 static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch)
77 {
78 struct wcn36xx_dxe_ctl *prev_ctl = NULL;
79 struct wcn36xx_dxe_ctl *cur_ctl = NULL;
80 int i;
81
82 spin_lock_init(&ch->lock);
83 for (i = 0; i < ch->desc_num; i++) {
84 cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL);
85 if (!cur_ctl)
86 goto out_fail;
87
88 spin_lock_init(&cur_ctl->skb_lock);
89 cur_ctl->ctl_blk_order = i;
90 if (i == 0) {
91 ch->head_blk_ctl = cur_ctl;
92 ch->tail_blk_ctl = cur_ctl;
93 } else if (ch->desc_num - 1 == i) {
94 prev_ctl->next = cur_ctl;
95 cur_ctl->next = ch->head_blk_ctl;
96 } else {
97 prev_ctl->next = cur_ctl;
98 }
99 prev_ctl = cur_ctl;
100 }
101
102 return 0;
103
104 out_fail:
105 wcn36xx_dxe_free_ctl_block(ch);
106 return -ENOMEM;
107 }
108
109 int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
110 {
111 int ret;
112
113 wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L;
114 wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H;
115 wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L;
116 wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H;
117
118 wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L;
119 wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H;
120 wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L;
121 wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H;
122
123 wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L;
124 wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H;
125
126 wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD;
127 wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD;
128
129 wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB;
130 wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB;
131
132 wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L;
133 wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H;
134
135 wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L;
136 wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H;
137
138 /* DXE control block allocation */
139 ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch);
140 if (ret)
141 goto out_err;
142 ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch);
143 if (ret)
144 goto out_err;
145 ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch);
146 if (ret)
147 goto out_err;
148 ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch);
149 if (ret)
150 goto out_err;
151
152 /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */
153 ret = wcn->ctrl_ops->smsm_change_state(
154 WCN36XX_SMSM_WLAN_TX_ENABLE,
155 WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
156
157 return 0;
158
159 out_err:
160 wcn36xx_err("Failed to allocate DXE control blocks\n");
161 wcn36xx_dxe_free_ctl_blks(wcn);
162 return -ENOMEM;
163 }
164
165 void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn)
166 {
167 wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_l_ch);
168 wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_h_ch);
169 wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_l_ch);
170 wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch);
171 }
172
173 static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch)
174 {
175 struct wcn36xx_dxe_desc *cur_dxe = NULL;
176 struct wcn36xx_dxe_desc *prev_dxe = NULL;
177 struct wcn36xx_dxe_ctl *cur_ctl = NULL;
178 size_t size;
179 int i;
180
181 size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
182 wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr,
183 GFP_KERNEL);
184 if (!wcn_ch->cpu_addr)
185 return -ENOMEM;
186
187 memset(wcn_ch->cpu_addr, 0, size);
188
189 cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr;
190 cur_ctl = wcn_ch->head_blk_ctl;
191
192 for (i = 0; i < wcn_ch->desc_num; i++) {
193 cur_ctl->desc = cur_dxe;
194 cur_ctl->desc_phy_addr = wcn_ch->dma_addr +
195 i * sizeof(struct wcn36xx_dxe_desc);
196
197 switch (wcn_ch->ch_type) {
198 case WCN36XX_DXE_CH_TX_L:
199 cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L;
200 cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L;
201 break;
202 case WCN36XX_DXE_CH_TX_H:
203 cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H;
204 cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H;
205 break;
206 case WCN36XX_DXE_CH_RX_L:
207 cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L;
208 cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_L;
209 break;
210 case WCN36XX_DXE_CH_RX_H:
211 cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_H;
212 cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_H;
213 break;
214 }
215 if (0 == i) {
216 cur_dxe->phy_next_l = 0;
217 } else if ((0 < i) && (i < wcn_ch->desc_num - 1)) {
218 prev_dxe->phy_next_l =
219 cur_ctl->desc_phy_addr;
220 } else if (i == (wcn_ch->desc_num - 1)) {
221 prev_dxe->phy_next_l =
222 cur_ctl->desc_phy_addr;
223 cur_dxe->phy_next_l =
224 wcn_ch->head_blk_ctl->desc_phy_addr;
225 }
226 cur_ctl = cur_ctl->next;
227 prev_dxe = cur_dxe;
228 cur_dxe++;
229 }
230
231 return 0;
232 }
233
234 static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch,
235 struct wcn36xx_dxe_mem_pool *pool)
236 {
237 int i, chunk_size = pool->chunk_size;
238 dma_addr_t bd_phy_addr = pool->phy_addr;
239 void *bd_cpu_addr = pool->virt_addr;
240 struct wcn36xx_dxe_ctl *cur = ch->head_blk_ctl;
241
242 for (i = 0; i < ch->desc_num; i++) {
243 /* Only every second dxe needs a bd pointer,
244 the other will point to the skb data */
245 if (!(i & 1)) {
246 cur->bd_phy_addr = bd_phy_addr;
247 cur->bd_cpu_addr = bd_cpu_addr;
248 bd_phy_addr += chunk_size;
249 bd_cpu_addr += chunk_size;
250 } else {
251 cur->bd_phy_addr = 0;
252 cur->bd_cpu_addr = NULL;
253 }
254 cur = cur->next;
255 }
256 }
257
258 static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch)
259 {
260 int reg_data = 0;
261
262 wcn36xx_dxe_read_register(wcn,
263 WCN36XX_DXE_INT_MASK_REG,
264 ®_data);
265
266 reg_data |= wcn_ch;
267
268 wcn36xx_dxe_write_register(wcn,
269 WCN36XX_DXE_INT_MASK_REG,
270 (int)reg_data);
271 return 0;
272 }
273
274 static int wcn36xx_dxe_fill_skb(struct device *dev, struct wcn36xx_dxe_ctl *ctl)
275 {
276 struct wcn36xx_dxe_desc *dxe = ctl->desc;
277 struct sk_buff *skb;
278
279 skb = alloc_skb(WCN36XX_PKT_SIZE, GFP_ATOMIC);
280 if (skb == NULL)
281 return -ENOMEM;
282
283 dxe->dst_addr_l = dma_map_single(dev,
284 skb_tail_pointer(skb),
285 WCN36XX_PKT_SIZE,
286 DMA_FROM_DEVICE);
287 ctl->skb = skb;
288
289 return 0;
290 }
291
292 static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn,
293 struct wcn36xx_dxe_ch *wcn_ch)
294 {
295 int i;
296 struct wcn36xx_dxe_ctl *cur_ctl = NULL;
297
298 cur_ctl = wcn_ch->head_blk_ctl;
299
300 for (i = 0; i < wcn_ch->desc_num; i++) {
301 wcn36xx_dxe_fill_skb(wcn->dev, cur_ctl);
302 cur_ctl = cur_ctl->next;
303 }
304
305 return 0;
306 }
307
308 static void wcn36xx_dxe_ch_free_skbs(struct wcn36xx *wcn,
309 struct wcn36xx_dxe_ch *wcn_ch)
310 {
311 struct wcn36xx_dxe_ctl *cur = wcn_ch->head_blk_ctl;
312 int i;
313
314 for (i = 0; i < wcn_ch->desc_num; i++) {
315 kfree_skb(cur->skb);
316 cur = cur->next;
317 }
318 }
319
320 void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status)
321 {
322 struct ieee80211_tx_info *info;
323 struct sk_buff *skb;
324 unsigned long flags;
325
326 spin_lock_irqsave(&wcn->dxe_lock, flags);
327 skb = wcn->tx_ack_skb;
328 wcn->tx_ack_skb = NULL;
329 spin_unlock_irqrestore(&wcn->dxe_lock, flags);
330
331 if (!skb) {
332 wcn36xx_warn("Spurious TX complete indication\n");
333 return;
334 }
335
336 info = IEEE80211_SKB_CB(skb);
337
338 if (status == 1)
339 info->flags |= IEEE80211_TX_STAT_ACK;
340
341 wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status);
342
343 ieee80211_tx_status_irqsafe(wcn->hw, skb);
344 ieee80211_wake_queues(wcn->hw);
345 }
346
347 static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
348 {
349 struct wcn36xx_dxe_ctl *ctl;
350 struct ieee80211_tx_info *info;
351 unsigned long flags;
352
353 /*
354 * Make at least one loop of do-while because in case ring is
355 * completely full head and tail are pointing to the same element
356 * and while-do will not make any cycles.
357 */
358 spin_lock_irqsave(&ch->lock, flags);
359 ctl = ch->tail_blk_ctl;
360 do {
361 if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)
362 break;
363 if (ctl->skb) {
364 dma_unmap_single(wcn->dev, ctl->desc->src_addr_l,
365 ctl->skb->len, DMA_TO_DEVICE);
366 info = IEEE80211_SKB_CB(ctl->skb);
367 if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
368 /* Keep frame until TX status comes */
369 ieee80211_free_txskb(wcn->hw, ctl->skb);
370 }
371 spin_lock(&ctl->skb_lock);
372 if (wcn->queues_stopped) {
373 wcn->queues_stopped = false;
374 ieee80211_wake_queues(wcn->hw);
375 }
376 spin_unlock(&ctl->skb_lock);
377
378 ctl->skb = NULL;
379 }
380 ctl = ctl->next;
381 } while (ctl != ch->head_blk_ctl &&
382 !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK));
383
384 ch->tail_blk_ctl = ctl;
385 spin_unlock_irqrestore(&ch->lock, flags);
386 }
387
388 static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
389 {
390 struct wcn36xx *wcn = (struct wcn36xx *)dev;
391 int int_src, int_reason;
392
393 wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src);
394
395 if (int_src & WCN36XX_INT_MASK_CHAN_TX_H) {
396 wcn36xx_dxe_read_register(wcn,
397 WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H,
398 &int_reason);
399
400 /* TODO: Check int_reason */
401
402 wcn36xx_dxe_write_register(wcn,
403 WCN36XX_DXE_0_INT_CLR,
404 WCN36XX_INT_MASK_CHAN_TX_H);
405
406 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR,
407 WCN36XX_INT_MASK_CHAN_TX_H);
408 wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n");
409 reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch);
410 }
411
412 if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) {
413 wcn36xx_dxe_read_register(wcn,
414 WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L,
415 &int_reason);
416 /* TODO: Check int_reason */
417
418 wcn36xx_dxe_write_register(wcn,
419 WCN36XX_DXE_0_INT_CLR,
420 WCN36XX_INT_MASK_CHAN_TX_L);
421
422 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR,
423 WCN36XX_INT_MASK_CHAN_TX_L);
424 wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n");
425 reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch);
426 }
427
428 return IRQ_HANDLED;
429 }
430
431 static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev)
432 {
433 struct wcn36xx *wcn = (struct wcn36xx *)dev;
434
435 disable_irq_nosync(wcn->rx_irq);
436 wcn36xx_dxe_rx_frame(wcn);
437 enable_irq(wcn->rx_irq);
438 return IRQ_HANDLED;
439 }
440
441 static int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn)
442 {
443 int ret;
444
445 ret = request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete,
446 IRQF_TRIGGER_HIGH, "wcn36xx_tx", wcn);
447 if (ret) {
448 wcn36xx_err("failed to alloc tx irq\n");
449 goto out_err;
450 }
451
452 ret = request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH,
453 "wcn36xx_rx", wcn);
454 if (ret) {
455 wcn36xx_err("failed to alloc rx irq\n");
456 goto out_txirq;
457 }
458
459 enable_irq_wake(wcn->rx_irq);
460
461 return 0;
462
463 out_txirq:
464 free_irq(wcn->tx_irq, wcn);
465 out_err:
466 return ret;
467
468 }
469
470 static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
471 struct wcn36xx_dxe_ch *ch)
472 {
473 struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl;
474 struct wcn36xx_dxe_desc *dxe = ctl->desc;
475 dma_addr_t dma_addr;
476 struct sk_buff *skb;
477 int ret = 0, int_mask;
478 u32 value;
479
480 if (ch->ch_type == WCN36XX_DXE_CH_RX_L) {
481 value = WCN36XX_DXE_CTRL_RX_L;
482 int_mask = WCN36XX_DXE_INT_CH1_MASK;
483 } else {
484 value = WCN36XX_DXE_CTRL_RX_H;
485 int_mask = WCN36XX_DXE_INT_CH3_MASK;
486 }
487
488 while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) {
489 skb = ctl->skb;
490 dma_addr = dxe->dst_addr_l;
491 ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl);
492 if (0 == ret) {
493 /* new skb allocation ok. Use the new one and queue
494 * the old one to network system.
495 */
496 dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
497 DMA_FROM_DEVICE);
498 wcn36xx_rx_skb(wcn, skb);
499 } /* else keep old skb not submitted and use it for rx DMA */
500
501 dxe->ctrl = value;
502 ctl = ctl->next;
503 dxe = ctl->desc;
504 }
505 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, int_mask);
506
507 ch->head_blk_ctl = ctl;
508 return 0;
509 }
510
511 void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn)
512 {
513 int int_src;
514
515 wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src);
516
517 /* RX_LOW_PRI */
518 if (int_src & WCN36XX_DXE_INT_CH1_MASK) {
519 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR,
520 WCN36XX_DXE_INT_CH1_MASK);
521 wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch));
522 }
523
524 /* RX_HIGH_PRI */
525 if (int_src & WCN36XX_DXE_INT_CH3_MASK) {
526 /* Clean up all the INT within this channel */
527 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR,
528 WCN36XX_DXE_INT_CH3_MASK);
529 wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch));
530 }
531
532 if (!int_src)
533 wcn36xx_warn("No DXE interrupt pending\n");
534 }
535
536 int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
537 {
538 size_t s;
539 void *cpu_addr;
540
541 /* Allocate BD headers for MGMT frames */
542
543 /* Where this come from ask QC */
544 wcn->mgmt_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE +
545 16 - (WCN36XX_BD_CHUNK_SIZE % 8);
546
547 s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H;
548 cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr,
549 GFP_KERNEL);
550 if (!cpu_addr)
551 goto out_err;
552
553 wcn->mgmt_mem_pool.virt_addr = cpu_addr;
554 memset(cpu_addr, 0, s);
555
556 /* Allocate BD headers for DATA frames */
557
558 /* Where this come from ask QC */
559 wcn->data_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE +
560 16 - (WCN36XX_BD_CHUNK_SIZE % 8);
561
562 s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L;
563 cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr,
564 GFP_KERNEL);
565 if (!cpu_addr)
566 goto out_err;
567
568 wcn->data_mem_pool.virt_addr = cpu_addr;
569 memset(cpu_addr, 0, s);
570
571 return 0;
572
573 out_err:
574 wcn36xx_dxe_free_mem_pools(wcn);
575 wcn36xx_err("Failed to allocate BD mempool\n");
576 return -ENOMEM;
577 }
578
579 void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn)
580 {
581 if (wcn->mgmt_mem_pool.virt_addr)
582 dma_free_coherent(wcn->dev, wcn->mgmt_mem_pool.chunk_size *
583 WCN36XX_DXE_CH_DESC_NUMB_TX_H,
584 wcn->mgmt_mem_pool.virt_addr,
585 wcn->mgmt_mem_pool.phy_addr);
586
587 if (wcn->data_mem_pool.virt_addr) {
588 dma_free_coherent(wcn->dev, wcn->data_mem_pool.chunk_size *
589 WCN36XX_DXE_CH_DESC_NUMB_TX_L,
590 wcn->data_mem_pool.virt_addr,
591 wcn->data_mem_pool.phy_addr);
592 }
593 }
594
595 int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
596 struct wcn36xx_vif *vif_priv,
597 struct sk_buff *skb,
598 bool is_low)
599 {
600 struct wcn36xx_dxe_ctl *ctl = NULL;
601 struct wcn36xx_dxe_desc *desc = NULL;
602 struct wcn36xx_dxe_ch *ch = NULL;
603 unsigned long flags;
604 int ret;
605
606 ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch;
607
608 spin_lock_irqsave(&ch->lock, flags);
609 ctl = ch->head_blk_ctl;
610
611 spin_lock(&ctl->next->skb_lock);
612
613 /*
614 * If skb is not null that means that we reached the tail of the ring
615 * hence ring is full. Stop queues to let mac80211 back off until ring
616 * has an empty slot again.
617 */
618 if (NULL != ctl->next->skb) {
619 ieee80211_stop_queues(wcn->hw);
620 wcn->queues_stopped = true;
621 spin_unlock(&ctl->next->skb_lock);
622 spin_unlock_irqrestore(&ch->lock, flags);
623 return -EBUSY;
624 }
625 spin_unlock(&ctl->next->skb_lock);
626
627 ctl->skb = NULL;
628 desc = ctl->desc;
629
630 /* Set source address of the BD we send */
631 desc->src_addr_l = ctl->bd_phy_addr;
632
633 desc->dst_addr_l = ch->dxe_wq;
634 desc->fr_len = sizeof(struct wcn36xx_tx_bd);
635 desc->ctrl = ch->ctrl_bd;
636
637 wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n");
638
639 wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ",
640 (char *)desc, sizeof(*desc));
641 wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP,
642 "BD >>> ", (char *)ctl->bd_cpu_addr,
643 sizeof(struct wcn36xx_tx_bd));
644
645 /* Set source address of the SKB we send */
646 ctl = ctl->next;
647 ctl->skb = skb;
648 desc = ctl->desc;
649 if (ctl->bd_cpu_addr) {
650 wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n");
651 ret = -EINVAL;
652 goto unlock;
653 }
654
655 desc->src_addr_l = dma_map_single(wcn->dev,
656 ctl->skb->data,
657 ctl->skb->len,
658 DMA_TO_DEVICE);
659
660 desc->dst_addr_l = ch->dxe_wq;
661 desc->fr_len = ctl->skb->len;
662
663 /* set dxe descriptor to VALID */
664 desc->ctrl = ch->ctrl_skb;
665
666 wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ",
667 (char *)desc, sizeof(*desc));
668 wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ",
669 (char *)ctl->skb->data, ctl->skb->len);
670
671 /* Move the head of the ring to the next empty descriptor */
672 ch->head_blk_ctl = ctl->next;
673
674 /*
675 * When connected and trying to send data frame chip can be in sleep
676 * mode and writing to the register will not wake up the chip. Instead
677 * notify chip about new frame through SMSM bus.
678 */
679 if (is_low && vif_priv->pw_state == WCN36XX_BMPS) {
680 wcn->ctrl_ops->smsm_change_state(
681 0,
682 WCN36XX_SMSM_WLAN_TX_ENABLE);
683 } else {
684 /* indicate End Of Packet and generate interrupt on descriptor
685 * done.
686 */
687 wcn36xx_dxe_write_register(wcn,
688 ch->reg_ctrl, ch->def_ctrl);
689 }
690
691 ret = 0;
692 unlock:
693 spin_unlock_irqrestore(&ch->lock, flags);
694 return ret;
695 }
696
697 int wcn36xx_dxe_init(struct wcn36xx *wcn)
698 {
699 int reg_data = 0, ret;
700
701 reg_data = WCN36XX_DXE_REG_RESET;
702 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
703
704 /* Setting interrupt path */
705 reg_data = WCN36XX_DXE_CCU_INT;
706 wcn36xx_dxe_write_register_x(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
707
708 /***************************************/
709 /* Init descriptors for TX LOW channel */
710 /***************************************/
711 wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
712 wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool);
713
714 /* Write channel head to a NEXT register */
715 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L,
716 wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr);
717
718 /* Program DMA destination addr for TX LOW */
719 wcn36xx_dxe_write_register(wcn,
720 WCN36XX_DXE_CH_DEST_ADDR_TX_L,
721 WCN36XX_DXE_WQ_TX_L);
722
723 wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data);
724 wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
725
726 /***************************************/
727 /* Init descriptors for TX HIGH channel */
728 /***************************************/
729 wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
730 wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool);
731
732 /* Write channel head to a NEXT register */
733 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H,
734 wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr);
735
736 /* Program DMA destination addr for TX HIGH */
737 wcn36xx_dxe_write_register(wcn,
738 WCN36XX_DXE_CH_DEST_ADDR_TX_H,
739 WCN36XX_DXE_WQ_TX_H);
740
741 wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data);
742
743 /* Enable channel interrupts */
744 wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
745
746 /***************************************/
747 /* Init descriptors for RX LOW channel */
748 /***************************************/
749 wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
750
751 /* For RX we need to preallocated buffers */
752 wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
753
754 /* Write channel head to a NEXT register */
755 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L,
756 wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr);
757
758 /* Write DMA source address */
759 wcn36xx_dxe_write_register(wcn,
760 WCN36XX_DXE_CH_SRC_ADDR_RX_L,
761 WCN36XX_DXE_WQ_RX_L);
762
763 /* Program preallocated destination address */
764 wcn36xx_dxe_write_register(wcn,
765 WCN36XX_DXE_CH_DEST_ADDR_RX_L,
766 wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l);
767
768 /* Enable default control registers */
769 wcn36xx_dxe_write_register(wcn,
770 WCN36XX_DXE_REG_CTL_RX_L,
771 WCN36XX_DXE_CH_DEFAULT_CTL_RX_L);
772
773 /* Enable channel interrupts */
774 wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);
775
776 /***************************************/
777 /* Init descriptors for RX HIGH channel */
778 /***************************************/
779 wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
780
781 /* For RX we need to prealocat buffers */
782 wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);
783
784 /* Write chanel head to a NEXT register */
785 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H,
786 wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr);
787
788 /* Write DMA source address */
789 wcn36xx_dxe_write_register(wcn,
790 WCN36XX_DXE_CH_SRC_ADDR_RX_H,
791 WCN36XX_DXE_WQ_RX_H);
792
793 /* Program preallocated destination address */
794 wcn36xx_dxe_write_register(wcn,
795 WCN36XX_DXE_CH_DEST_ADDR_RX_H,
796 wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l);
797
798 /* Enable default control registers */
799 wcn36xx_dxe_write_register(wcn,
800 WCN36XX_DXE_REG_CTL_RX_H,
801 WCN36XX_DXE_CH_DEFAULT_CTL_RX_H);
802
803 /* Enable channel interrupts */
804 wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);
805
806 ret = wcn36xx_dxe_request_irqs(wcn);
807 if (ret < 0)
808 goto out_err;
809
810 return 0;
811
812 out_err:
813 return ret;
814 }
815
816 void wcn36xx_dxe_deinit(struct wcn36xx *wcn)
817 {
818 free_irq(wcn->tx_irq, wcn);
819 free_irq(wcn->rx_irq, wcn);
820
821 if (wcn->tx_ack_skb) {
822 ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb);
823 wcn->tx_ack_skb = NULL;
824 }
825
826 wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch);
827 wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch);
828 } 1
2 #include <linux/kernel.h>
3 #include <linux/mutex.h>
4 #include <linux/spinlock.h>
5 #include <linux/errno.h>
6 #include <verifier/rcv.h>
7 #include <linux/list.h>
8
9 /* mutexes */
10 extern int mutex_lock_interruptible(struct mutex *lock);
11 extern int mutex_lock_killable(struct mutex *lock);
12 extern void mutex_lock(struct mutex *lock);
13
14 /* mutex model functions */
15 extern void ldv_mutex_lock(struct mutex *lock, char *sign);
16 extern int ldv_mutex_is_locked(struct mutex *lock, char *sign);
17 extern void ldv_mutex_unlock(struct mutex *lock, char *sign);
18
19
20 /* Spin locks */
21 extern void __ldv_spin_lock(spinlock_t *lock);
22 extern void __ldv_spin_unlock(spinlock_t *lock);
23 extern int __ldv_spin_trylock(spinlock_t *lock);
24 extern void __ldv_spin_unlock_wait(spinlock_t *lock);
25 extern void __ldv_spin_can_lock(spinlock_t *lock);
26 extern int __ldv_atomic_dec_and_lock(spinlock_t *lock);
27
28 /* spin model functions */
29 extern void ldv_spin_lock(spinlock_t *lock, char *sign);
30 extern void ldv_spin_unlock(spinlock_t *lock, char *sign);
31 extern int ldv_spin_is_locked(spinlock_t *lock, char *sign);
32
33 /* Support for list binder functions */
34 static inline struct list_head *ldv_list_get_first(struct list_head *head) {
35 return head->next;
36 }
37
38 static inline int ldv_list_is_stop(struct list_head *pos, struct list_head *head) {
39 return pos==head;
40 }
41
42 static inline struct list_head *ldv_list_get_next(struct list_head *pos) {
43 return pos->next;
44 }
45
46 #include <linux/mutex.h>
47 #include <linux/slab.h>
48 #include <linux/irqreturn.h>
49 #include <verifier/rcv.h>
50 #include <linux/rtnetlink.h>
51 #include <linux/gfp.h>
52 extern void* ldv_irq_data_2_1;
53 extern int ldv_irq_1_3=0;
54 extern int ldv_irq_line_2_2;
55 extern void* ldv_irq_data_1_1;
56 extern int ldv_irq_1_0=0;
57 extern int probed_5=0;
58 extern struct file *fops_wcn36xx_bmps_group2;
59 extern int ldv_state_variable_6;
60 extern void* ldv_irq_data_1_0;
61 extern int ldv_state_variable_0;
62 extern int ldv_state_variable_5;
63 extern int ldv_irq_line_2_1;
64 extern int ldv_state_variable_2;
65 extern int ldv_irq_2_0=0;
66 extern void* ldv_irq_data_1_3;
67 extern void* ldv_irq_data_1_2;
68 extern struct file *fops_wcn36xx_dump_group2;
69 extern void* ldv_irq_data_2_0;
70 extern struct inode *fops_wcn36xx_dump_group1;
71 extern int ldv_irq_1_2=0;
72 extern int LDV_IN_INTERRUPT = 1;
73 extern int ldv_irq_1_1=0;
74 extern int ldv_irq_2_3=0;
75 extern void* ldv_irq_data_2_3;
76 extern int ldv_irq_line_1_3;
77 extern int ldv_irq_2_2=0;
78 extern struct mutex fs_mutex;
79 extern int ldv_irq_line_2_0;
80 extern int ldv_state_variable_3;
81 extern int ldv_irq_line_1_0;
82 extern struct platform_device *wcn36xx_driver_group1;
83 extern struct mutex ar_mutex;
84 extern int ref_cnt;
85 extern struct mutex key_mtx;
86 extern int ldv_irq_line_1_1;
87 extern void* ldv_irq_data_2_2;
88 extern struct ieee80211_hw *wcn36xx_ops_group0;
89 extern int ldv_state_variable_1;
90 extern struct inode *fops_wcn36xx_bmps_group1;
91 extern int ldv_irq_line_1_2;
92 extern int ldv_state_variable_4;
93 extern int ldv_irq_line_2_3;
94 extern int ldv_irq_2_1=0;
95 extern void ldv_initialyze_ieee80211_ops_6(void);
96 extern int evil_hack_key_6(void);
97 extern void ldv_file_operations_3(void);
98 extern void choose_interrupt_2(void);
99 extern void disable_suitable_irq_2(int line, void * data);
100 extern int evil_hack_6(void);
101 extern void ldv_platform_probe_5(int (*probe)(struct platform_device *));
102 extern void activate_suitable_irq_2(int line, void * data);
103 extern void disable_suitable_irq_1(int line, void * data);
104 extern int reg_check_1(irqreturn_t (*handler)(int, void *));
105 extern void activate_suitable_irq_1(int line, void * data);
106 extern int ldv_irq_1(int state, int line, void *data);
107 extern int evil_hack_fs_lock(void);
108 extern int __VERIFIER_nondet_int(void);
109 extern void ldv_platform_driver_init_5(void);
110 extern int ldv_irq_2(int state, int line, void *data);
111 extern int evil_hack_ar_lock(void);
112 extern void choose_interrupt_1(void);
113 extern int reg_check_2(irqreturn_t (*handler)(int, void *));
114 extern void ldv_file_operations_4(void);
115 #line 1 "/work/ldvuser/andrianov/work/current--X--drivers/net/wireless/ath/wcn36xx/--X--defaultlinux-4.5-rc7--X--races--X--cpachecker/linux-4.5-rc7/csd_deg_dscv/19/dscv_tempdir/dscv/ri/races/drivers/net/wireless/ath/wcn36xx/dxe.c"
116 /*
117 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
118 *
119 * Permission to use, copy, modify, and/or distribute this software for any
120 * purpose with or without fee is hereby granted, provided that the above
121 * copyright notice and this permission notice appear in all copies.
122 *
123 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
124 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
125 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
126 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
127 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
128 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
129 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
130 */
131
132 /* DXE - DMA transfer engine
133 * we have 2 channels(High prio and Low prio) for TX and 2 channels for RX.
134 * through low channels data packets are transfered
135 * through high channels managment packets are transfered
136 */
137
138 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
139
140 #include <linux/interrupt.h>
141 #include "wcn36xx.h"
142 #include "txrx.h"
143
144 void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low)
145 {
146 struct wcn36xx_dxe_ch *ch = is_low ?
147 &wcn->dxe_tx_l_ch :
148 &wcn->dxe_tx_h_ch;
149
150 return ch->head_blk_ctl->bd_cpu_addr;
151 }
152
153 static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
154 {
155 wcn36xx_dbg(WCN36XX_DBG_DXE,
156 "wcn36xx_dxe_write_register: addr=%x, data=%x\n",
157 addr, data);
158
159 writel(data, wcn->mmio + addr);
160 }
161
162 #define wcn36xx_dxe_write_register_x(wcn, reg, reg_data) \
163 do { \
164 if (wcn->chip_version == WCN36XX_CHIP_3680) \
165 wcn36xx_dxe_write_register(wcn, reg ## _3680, reg_data); \
166 else \
167 wcn36xx_dxe_write_register(wcn, reg ## _3660, reg_data); \
168 } while (0) \
169
170 static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
171 {
172 *data = readl(wcn->mmio + addr);
173
174 wcn36xx_dbg(WCN36XX_DBG_DXE,
175 "wcn36xx_dxe_read_register: addr=%x, data=%x\n",
176 addr, *data);
177 }
178
179 static void wcn36xx_dxe_free_ctl_block(struct wcn36xx_dxe_ch *ch)
180 {
181 struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl, *next;
182 int i;
183
184 for (i = 0; i < ch->desc_num && ctl; i++) {
185 next = ctl->next;
186 kfree(ctl);
187 ctl = next;
188 }
189 }
190
191 static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch)
192 {
193 struct wcn36xx_dxe_ctl *prev_ctl = NULL;
194 struct wcn36xx_dxe_ctl *cur_ctl = NULL;
195 int i;
196
197 spin_lock_init(&ch->lock);
198 for (i = 0; i < ch->desc_num; i++) {
199 cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL);
200 if (!cur_ctl)
201 goto out_fail;
202
203 spin_lock_init(&cur_ctl->skb_lock);
204 cur_ctl->ctl_blk_order = i;
205 if (i == 0) {
206 ch->head_blk_ctl = cur_ctl;
207 ch->tail_blk_ctl = cur_ctl;
208 } else if (ch->desc_num - 1 == i) {
209 prev_ctl->next = cur_ctl;
210 cur_ctl->next = ch->head_blk_ctl;
211 } else {
212 prev_ctl->next = cur_ctl;
213 }
214 prev_ctl = cur_ctl;
215 }
216
217 return 0;
218
219 out_fail:
220 wcn36xx_dxe_free_ctl_block(ch);
221 return -ENOMEM;
222 }
223
224 int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
225 {
226 int ret;
227
228 wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L;
229 wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H;
230 wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L;
231 wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H;
232
233 wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L;
234 wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H;
235 wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L;
236 wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H;
237
238 wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L;
239 wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H;
240
241 wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD;
242 wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD;
243
244 wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB;
245 wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB;
246
247 wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L;
248 wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H;
249
250 wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L;
251 wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H;
252
253 /* DXE control block allocation */
254 ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch);
255 if (ret)
256 goto out_err;
257 ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch);
258 if (ret)
259 goto out_err;
260 ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch);
261 if (ret)
262 goto out_err;
263 ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch);
264 if (ret)
265 goto out_err;
266
267 /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */
268 ret = wcn->ctrl_ops->smsm_change_state(
269 WCN36XX_SMSM_WLAN_TX_ENABLE,
270 WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
271
272 return 0;
273
274 out_err:
275 wcn36xx_err("Failed to allocate DXE control blocks\n");
276 wcn36xx_dxe_free_ctl_blks(wcn);
277 return -ENOMEM;
278 }
279
280 void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn)
281 {
282 wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_l_ch);
283 wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_h_ch);
284 wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_l_ch);
285 wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch);
286 }
287
288 static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch)
289 {
290 struct wcn36xx_dxe_desc *cur_dxe = NULL;
291 struct wcn36xx_dxe_desc *prev_dxe = NULL;
292 struct wcn36xx_dxe_ctl *cur_ctl = NULL;
293 size_t size;
294 int i;
295
296 size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
297 wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr,
298 GFP_KERNEL);
299 if (!wcn_ch->cpu_addr)
300 return -ENOMEM;
301
302 memset(wcn_ch->cpu_addr, 0, size);
303
304 cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr;
305 cur_ctl = wcn_ch->head_blk_ctl;
306
307 for (i = 0; i < wcn_ch->desc_num; i++) {
308 cur_ctl->desc = cur_dxe;
309 cur_ctl->desc_phy_addr = wcn_ch->dma_addr +
310 i * sizeof(struct wcn36xx_dxe_desc);
311
312 switch (wcn_ch->ch_type) {
313 case WCN36XX_DXE_CH_TX_L:
314 cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L;
315 cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L;
316 break;
317 case WCN36XX_DXE_CH_TX_H:
318 cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H;
319 cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H;
320 break;
321 case WCN36XX_DXE_CH_RX_L:
322 cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L;
323 cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_L;
324 break;
325 case WCN36XX_DXE_CH_RX_H:
326 cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_H;
327 cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_H;
328 break;
329 }
330 if (0 == i) {
331 cur_dxe->phy_next_l = 0;
332 } else if ((0 < i) && (i < wcn_ch->desc_num - 1)) {
333 prev_dxe->phy_next_l =
334 cur_ctl->desc_phy_addr;
335 } else if (i == (wcn_ch->desc_num - 1)) {
336 prev_dxe->phy_next_l =
337 cur_ctl->desc_phy_addr;
338 cur_dxe->phy_next_l =
339 wcn_ch->head_blk_ctl->desc_phy_addr;
340 }
341 cur_ctl = cur_ctl->next;
342 prev_dxe = cur_dxe;
343 cur_dxe++;
344 }
345
346 return 0;
347 }
348
349 static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch,
350 struct wcn36xx_dxe_mem_pool *pool)
351 {
352 int i, chunk_size = pool->chunk_size;
353 dma_addr_t bd_phy_addr = pool->phy_addr;
354 void *bd_cpu_addr = pool->virt_addr;
355 struct wcn36xx_dxe_ctl *cur = ch->head_blk_ctl;
356
357 for (i = 0; i < ch->desc_num; i++) {
358 /* Only every second dxe needs a bd pointer,
359 the other will point to the skb data */
360 if (!(i & 1)) {
361 cur->bd_phy_addr = bd_phy_addr;
362 cur->bd_cpu_addr = bd_cpu_addr;
363 bd_phy_addr += chunk_size;
364 bd_cpu_addr += chunk_size;
365 } else {
366 cur->bd_phy_addr = 0;
367 cur->bd_cpu_addr = NULL;
368 }
369 cur = cur->next;
370 }
371 }
372
373 static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch)
374 {
375 int reg_data = 0;
376
377 wcn36xx_dxe_read_register(wcn,
378 WCN36XX_DXE_INT_MASK_REG,
379 ®_data);
380
381 reg_data |= wcn_ch;
382
383 wcn36xx_dxe_write_register(wcn,
384 WCN36XX_DXE_INT_MASK_REG,
385 (int)reg_data);
386 return 0;
387 }
388
389 static int wcn36xx_dxe_fill_skb(struct device *dev, struct wcn36xx_dxe_ctl *ctl)
390 {
391 struct wcn36xx_dxe_desc *dxe = ctl->desc;
392 struct sk_buff *skb;
393
394 skb = alloc_skb(WCN36XX_PKT_SIZE, GFP_ATOMIC);
395 if (skb == NULL)
396 return -ENOMEM;
397
398 dxe->dst_addr_l = dma_map_single(dev,
399 skb_tail_pointer(skb),
400 WCN36XX_PKT_SIZE,
401 DMA_FROM_DEVICE);
402 ctl->skb = skb;
403
404 return 0;
405 }
406
407 static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn,
408 struct wcn36xx_dxe_ch *wcn_ch)
409 {
410 int i;
411 struct wcn36xx_dxe_ctl *cur_ctl = NULL;
412
413 cur_ctl = wcn_ch->head_blk_ctl;
414
415 for (i = 0; i < wcn_ch->desc_num; i++) {
416 wcn36xx_dxe_fill_skb(wcn->dev, cur_ctl);
417 cur_ctl = cur_ctl->next;
418 }
419
420 return 0;
421 }
422
423 static void wcn36xx_dxe_ch_free_skbs(struct wcn36xx *wcn,
424 struct wcn36xx_dxe_ch *wcn_ch)
425 {
426 struct wcn36xx_dxe_ctl *cur = wcn_ch->head_blk_ctl;
427 int i;
428
429 for (i = 0; i < wcn_ch->desc_num; i++) {
430 kfree_skb(cur->skb);
431 cur = cur->next;
432 }
433 }
434
435 void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status)
436 {
437 struct ieee80211_tx_info *info;
438 struct sk_buff *skb;
439 unsigned long flags;
440
441 spin_lock_irqsave(&wcn->dxe_lock, flags);
442 skb = wcn->tx_ack_skb;
443 wcn->tx_ack_skb = NULL;
444 spin_unlock_irqrestore(&wcn->dxe_lock, flags);
445
446 if (!skb) {
447 wcn36xx_warn("Spurious TX complete indication\n");
448 return;
449 }
450
451 info = IEEE80211_SKB_CB(skb);
452
453 if (status == 1)
454 info->flags |= IEEE80211_TX_STAT_ACK;
455
456 wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status);
457
458 ieee80211_tx_status_irqsafe(wcn->hw, skb);
459 ieee80211_wake_queues(wcn->hw);
460 }
461
462 static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
463 {
464 struct wcn36xx_dxe_ctl *ctl;
465 struct ieee80211_tx_info *info;
466 unsigned long flags;
467
468 /*
469 * Make at least one loop of do-while because in case ring is
470 * completely full head and tail are pointing to the same element
471 * and while-do will not make any cycles.
472 */
473 spin_lock_irqsave(&ch->lock, flags);
474 ctl = ch->tail_blk_ctl;
475 do {
476 if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)
477 break;
478 if (ctl->skb) {
479 dma_unmap_single(wcn->dev, ctl->desc->src_addr_l,
480 ctl->skb->len, DMA_TO_DEVICE);
481 info = IEEE80211_SKB_CB(ctl->skb);
482 if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
483 /* Keep frame until TX status comes */
484 ieee80211_free_txskb(wcn->hw, ctl->skb);
485 }
486 spin_lock(&ctl->skb_lock);
487 if (wcn->queues_stopped) {
488 wcn->queues_stopped = false;
489 ieee80211_wake_queues(wcn->hw);
490 }
491 spin_unlock(&ctl->skb_lock);
492
493 ctl->skb = NULL;
494 }
495 ctl = ctl->next;
496 } while (ctl != ch->head_blk_ctl &&
497 !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK));
498
499 ch->tail_blk_ctl = ctl;
500 spin_unlock_irqrestore(&ch->lock, flags);
501 }
502
503 static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
504 {
505 struct wcn36xx *wcn = (struct wcn36xx *)dev;
506 int int_src, int_reason;
507
508 wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src);
509
510 if (int_src & WCN36XX_INT_MASK_CHAN_TX_H) {
511 wcn36xx_dxe_read_register(wcn,
512 WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H,
513 &int_reason);
514
515 /* TODO: Check int_reason */
516
517 wcn36xx_dxe_write_register(wcn,
518 WCN36XX_DXE_0_INT_CLR,
519 WCN36XX_INT_MASK_CHAN_TX_H);
520
521 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR,
522 WCN36XX_INT_MASK_CHAN_TX_H);
523 wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n");
524 reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch);
525 }
526
527 if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) {
528 wcn36xx_dxe_read_register(wcn,
529 WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L,
530 &int_reason);
531 /* TODO: Check int_reason */
532
533 wcn36xx_dxe_write_register(wcn,
534 WCN36XX_DXE_0_INT_CLR,
535 WCN36XX_INT_MASK_CHAN_TX_L);
536
537 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR,
538 WCN36XX_INT_MASK_CHAN_TX_L);
539 wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n");
540 reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch);
541 }
542
543 return IRQ_HANDLED;
544 }
545
546 static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev)
547 {
548 struct wcn36xx *wcn = (struct wcn36xx *)dev;
549
550 disable_irq_nosync(wcn->rx_irq);
551 wcn36xx_dxe_rx_frame(wcn);
552 enable_irq(wcn->rx_irq);
553 return IRQ_HANDLED;
554 }
555
556 static int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn)
557 {
558 int ret;
559
560 ret = request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete,
561 IRQF_TRIGGER_HIGH, "wcn36xx_tx", wcn);
562 if (ret) {
563 wcn36xx_err("failed to alloc tx irq\n");
564 goto out_err;
565 }
566
567 ret = request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH,
568 "wcn36xx_rx", wcn);
569 if (ret) {
570 wcn36xx_err("failed to alloc rx irq\n");
571 goto out_txirq;
572 }
573
574 enable_irq_wake(wcn->rx_irq);
575
576 return 0;
577
578 out_txirq:
579 free_irq(wcn->tx_irq, wcn);
580 out_err:
581 return ret;
582
583 }
584
585 static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
586 struct wcn36xx_dxe_ch *ch)
587 {
588 struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl;
589 struct wcn36xx_dxe_desc *dxe = ctl->desc;
590 dma_addr_t dma_addr;
591 struct sk_buff *skb;
592 int ret = 0, int_mask;
593 u32 value;
594
595 if (ch->ch_type == WCN36XX_DXE_CH_RX_L) {
596 value = WCN36XX_DXE_CTRL_RX_L;
597 int_mask = WCN36XX_DXE_INT_CH1_MASK;
598 } else {
599 value = WCN36XX_DXE_CTRL_RX_H;
600 int_mask = WCN36XX_DXE_INT_CH3_MASK;
601 }
602
603 while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) {
604 skb = ctl->skb;
605 dma_addr = dxe->dst_addr_l;
606 ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl);
607 if (0 == ret) {
608 /* new skb allocation ok. Use the new one and queue
609 * the old one to network system.
610 */
611 dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
612 DMA_FROM_DEVICE);
613 wcn36xx_rx_skb(wcn, skb);
614 } /* else keep old skb not submitted and use it for rx DMA */
615
616 dxe->ctrl = value;
617 ctl = ctl->next;
618 dxe = ctl->desc;
619 }
620 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, int_mask);
621
622 ch->head_blk_ctl = ctl;
623 return 0;
624 }
625
626 void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn)
627 {
628 int int_src;
629
630 wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src);
631
632 /* RX_LOW_PRI */
633 if (int_src & WCN36XX_DXE_INT_CH1_MASK) {
634 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR,
635 WCN36XX_DXE_INT_CH1_MASK);
636 wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch));
637 }
638
639 /* RX_HIGH_PRI */
640 if (int_src & WCN36XX_DXE_INT_CH3_MASK) {
641 /* Clean up all the INT within this channel */
642 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR,
643 WCN36XX_DXE_INT_CH3_MASK);
644 wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch));
645 }
646
647 if (!int_src)
648 wcn36xx_warn("No DXE interrupt pending\n");
649 }
650
651 int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
652 {
653 size_t s;
654 void *cpu_addr;
655
656 /* Allocate BD headers for MGMT frames */
657
658 /* Where this come from ask QC */
659 wcn->mgmt_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE +
660 16 - (WCN36XX_BD_CHUNK_SIZE % 8);
661
662 s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H;
663 cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr,
664 GFP_KERNEL);
665 if (!cpu_addr)
666 goto out_err;
667
668 wcn->mgmt_mem_pool.virt_addr = cpu_addr;
669 memset(cpu_addr, 0, s);
670
671 /* Allocate BD headers for DATA frames */
672
673 /* Where this come from ask QC */
674 wcn->data_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE +
675 16 - (WCN36XX_BD_CHUNK_SIZE % 8);
676
677 s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L;
678 cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr,
679 GFP_KERNEL);
680 if (!cpu_addr)
681 goto out_err;
682
683 wcn->data_mem_pool.virt_addr = cpu_addr;
684 memset(cpu_addr, 0, s);
685
686 return 0;
687
688 out_err:
689 wcn36xx_dxe_free_mem_pools(wcn);
690 wcn36xx_err("Failed to allocate BD mempool\n");
691 return -ENOMEM;
692 }
693
694 void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn)
695 {
696 if (wcn->mgmt_mem_pool.virt_addr)
697 dma_free_coherent(wcn->dev, wcn->mgmt_mem_pool.chunk_size *
698 WCN36XX_DXE_CH_DESC_NUMB_TX_H,
699 wcn->mgmt_mem_pool.virt_addr,
700 wcn->mgmt_mem_pool.phy_addr);
701
702 if (wcn->data_mem_pool.virt_addr) {
703 dma_free_coherent(wcn->dev, wcn->data_mem_pool.chunk_size *
704 WCN36XX_DXE_CH_DESC_NUMB_TX_L,
705 wcn->data_mem_pool.virt_addr,
706 wcn->data_mem_pool.phy_addr);
707 }
708 }
709
710 int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
711 struct wcn36xx_vif *vif_priv,
712 struct sk_buff *skb,
713 bool is_low)
714 {
715 struct wcn36xx_dxe_ctl *ctl = NULL;
716 struct wcn36xx_dxe_desc *desc = NULL;
717 struct wcn36xx_dxe_ch *ch = NULL;
718 unsigned long flags;
719 int ret;
720
721 ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch;
722
723 spin_lock_irqsave(&ch->lock, flags);
724 ctl = ch->head_blk_ctl;
725
726 spin_lock(&ctl->next->skb_lock);
727
728 /*
729 * If skb is not null that means that we reached the tail of the ring
730 * hence ring is full. Stop queues to let mac80211 back off until ring
731 * has an empty slot again.
732 */
733 if (NULL != ctl->next->skb) {
734 ieee80211_stop_queues(wcn->hw);
735 wcn->queues_stopped = true;
736 spin_unlock(&ctl->next->skb_lock);
737 spin_unlock_irqrestore(&ch->lock, flags);
738 return -EBUSY;
739 }
740 spin_unlock(&ctl->next->skb_lock);
741
742 ctl->skb = NULL;
743 desc = ctl->desc;
744
745 /* Set source address of the BD we send */
746 desc->src_addr_l = ctl->bd_phy_addr;
747
748 desc->dst_addr_l = ch->dxe_wq;
749 desc->fr_len = sizeof(struct wcn36xx_tx_bd);
750 desc->ctrl = ch->ctrl_bd;
751
752 wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n");
753
754 wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ",
755 (char *)desc, sizeof(*desc));
756 wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP,
757 "BD >>> ", (char *)ctl->bd_cpu_addr,
758 sizeof(struct wcn36xx_tx_bd));
759
760 /* Set source address of the SKB we send */
761 ctl = ctl->next;
762 ctl->skb = skb;
763 desc = ctl->desc;
764 if (ctl->bd_cpu_addr) {
765 wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n");
766 ret = -EINVAL;
767 goto unlock;
768 }
769
770 desc->src_addr_l = dma_map_single(wcn->dev,
771 ctl->skb->data,
772 ctl->skb->len,
773 DMA_TO_DEVICE);
774
775 desc->dst_addr_l = ch->dxe_wq;
776 desc->fr_len = ctl->skb->len;
777
778 /* set dxe descriptor to VALID */
779 desc->ctrl = ch->ctrl_skb;
780
781 wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ",
782 (char *)desc, sizeof(*desc));
783 wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ",
784 (char *)ctl->skb->data, ctl->skb->len);
785
786 /* Move the head of the ring to the next empty descriptor */
787 ch->head_blk_ctl = ctl->next;
788
789 /*
790 * When connected and trying to send data frame chip can be in sleep
791 * mode and writing to the register will not wake up the chip. Instead
792 * notify chip about new frame through SMSM bus.
793 */
794 if (is_low && vif_priv->pw_state == WCN36XX_BMPS) {
795 wcn->ctrl_ops->smsm_change_state(
796 0,
797 WCN36XX_SMSM_WLAN_TX_ENABLE);
798 } else {
799 /* indicate End Of Packet and generate interrupt on descriptor
800 * done.
801 */
802 wcn36xx_dxe_write_register(wcn,
803 ch->reg_ctrl, ch->def_ctrl);
804 }
805
806 ret = 0;
807 unlock:
808 spin_unlock_irqrestore(&ch->lock, flags);
809 return ret;
810 }
811
812 int wcn36xx_dxe_init(struct wcn36xx *wcn)
813 {
814 int reg_data = 0, ret;
815
816 reg_data = WCN36XX_DXE_REG_RESET;
817 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
818
819 /* Setting interrupt path */
820 reg_data = WCN36XX_DXE_CCU_INT;
821 wcn36xx_dxe_write_register_x(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
822
823 /***************************************/
824 /* Init descriptors for TX LOW channel */
825 /***************************************/
826 wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
827 wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool);
828
829 /* Write channel head to a NEXT register */
830 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L,
831 wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr);
832
833 /* Program DMA destination addr for TX LOW */
834 wcn36xx_dxe_write_register(wcn,
835 WCN36XX_DXE_CH_DEST_ADDR_TX_L,
836 WCN36XX_DXE_WQ_TX_L);
837
838 wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data);
839 wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
840
841 /***************************************/
842 /* Init descriptors for TX HIGH channel */
843 /***************************************/
844 wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
845 wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool);
846
847 /* Write channel head to a NEXT register */
848 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H,
849 wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr);
850
851 /* Program DMA destination addr for TX HIGH */
852 wcn36xx_dxe_write_register(wcn,
853 WCN36XX_DXE_CH_DEST_ADDR_TX_H,
854 WCN36XX_DXE_WQ_TX_H);
855
856 wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data);
857
858 /* Enable channel interrupts */
859 wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
860
861 /***************************************/
862 /* Init descriptors for RX LOW channel */
863 /***************************************/
864 wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
865
866 /* For RX we need to preallocated buffers */
867 wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
868
869 /* Write channel head to a NEXT register */
870 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L,
871 wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr);
872
873 /* Write DMA source address */
874 wcn36xx_dxe_write_register(wcn,
875 WCN36XX_DXE_CH_SRC_ADDR_RX_L,
876 WCN36XX_DXE_WQ_RX_L);
877
878 /* Program preallocated destination address */
879 wcn36xx_dxe_write_register(wcn,
880 WCN36XX_DXE_CH_DEST_ADDR_RX_L,
881 wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l);
882
883 /* Enable default control registers */
884 wcn36xx_dxe_write_register(wcn,
885 WCN36XX_DXE_REG_CTL_RX_L,
886 WCN36XX_DXE_CH_DEFAULT_CTL_RX_L);
887
888 /* Enable channel interrupts */
889 wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);
890
891 /***************************************/
892 /* Init descriptors for RX HIGH channel */
893 /***************************************/
894 wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
895
896 /* For RX we need to prealocat buffers */
897 wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);
898
899 /* Write chanel head to a NEXT register */
900 wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H,
901 wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr);
902
903 /* Write DMA source address */
904 wcn36xx_dxe_write_register(wcn,
905 WCN36XX_DXE_CH_SRC_ADDR_RX_H,
906 WCN36XX_DXE_WQ_RX_H);
907
908 /* Program preallocated destination address */
909 wcn36xx_dxe_write_register(wcn,
910 WCN36XX_DXE_CH_DEST_ADDR_RX_H,
911 wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l);
912
913 /* Enable default control registers */
914 wcn36xx_dxe_write_register(wcn,
915 WCN36XX_DXE_REG_CTL_RX_H,
916 WCN36XX_DXE_CH_DEFAULT_CTL_RX_H);
917
918 /* Enable channel interrupts */
919 wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);
920
921 ret = wcn36xx_dxe_request_irqs(wcn);
922 if (ret < 0)
923 goto out_err;
924
925 return 0;
926
927 out_err:
928 return ret;
929 }
930
931 void wcn36xx_dxe_deinit(struct wcn36xx *wcn)
932 {
933 free_irq(wcn->tx_irq, wcn);
934 free_irq(wcn->rx_irq, wcn);
935
936 if (wcn->tx_ack_skb) {
937 ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb);
938 wcn->tx_ack_skb = NULL;
939 }
940
941 wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch);
942 wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch);
943 }
944
945 #line 115 "/work/ldvuser/andrianov/work/current--X--drivers/net/wireless/ath/wcn36xx/--X--defaultlinux-4.5-rc7--X--races--X--cpachecker/linux-4.5-rc7/csd_deg_dscv/19/dscv_tempdir/dscv/ri/races/drivers/net/wireless/ath/wcn36xx/dxe.o.c.prepared"
946
947
948 void choose_interrupt_2(void){
949 switch(__VERIFIER_nondet_int()){
950 case 0: {
951 ldv_irq_2_0 = ldv_irq_2(ldv_irq_2_0, ldv_irq_line_2_0, ldv_irq_data_2_0);
952 }
953 break;
954 case 1: {
955 ldv_irq_2_0 = ldv_irq_2(ldv_irq_2_1, ldv_irq_line_2_1, ldv_irq_data_2_1);
956 }
957 break;
958 case 2: {
959 ldv_irq_2_0 = ldv_irq_2(ldv_irq_2_2, ldv_irq_line_2_2, ldv_irq_data_2_2);
960 }
961 break;
962 case 3: {
963 ldv_irq_2_0 = ldv_irq_2(ldv_irq_2_3, ldv_irq_line_2_3, ldv_irq_data_2_3);
964 }
965 break;
966 default: ldv_assume(0);
967 }
968 return;
969 }
970
971
972 void disable_suitable_irq_2(int line, void * data){
973 if(ldv_irq_2_0 != 0 && line == ldv_irq_line_2_0){
974 ldv_irq_2_0 = 0;
975 return;
976 }
977 if(ldv_irq_2_1 != 0 && line == ldv_irq_line_2_1){
978 ldv_irq_2_1 = 0;
979 return;
980 }
981 if(ldv_irq_2_2 != 0 && line == ldv_irq_line_2_2){
982 ldv_irq_2_2 = 0;
983 return;
984 }
985 if(ldv_irq_2_3 != 0 && line == ldv_irq_line_2_3){
986 ldv_irq_2_3 = 0;
987 return;
988 }
989 return;
990 }
991
992
993 void activate_suitable_irq_2(int line, void * data){
994 if(ldv_irq_2_0 == 0){
995 ldv_irq_line_2_0 = line;
996 ldv_irq_data_2_0 = data;
997 ldv_irq_2_0 = 1;
998 return;
999 }
1000 if(ldv_irq_2_1 == 0){
1001 ldv_irq_line_2_1 = line;
1002 ldv_irq_data_2_1 = data;
1003 ldv_irq_2_1 = 1;
1004 return;
1005 }
1006 if(ldv_irq_2_2 == 0){
1007 ldv_irq_line_2_2 = line;
1008 ldv_irq_data_2_2 = data;
1009 ldv_irq_2_2 = 1;
1010 return;
1011 }
1012 if(ldv_irq_2_3 == 0){
1013 ldv_irq_line_2_3 = line;
1014 ldv_irq_data_2_3 = data;
1015 ldv_irq_2_3 = 1;
1016 return;
1017 }
1018 return;
1019 }
1020
1021
1022 void disable_suitable_irq_1(int line, void * data){
1023 if(ldv_irq_1_0 != 0 && line == ldv_irq_line_1_0){
1024 ldv_irq_1_0 = 0;
1025 return;
1026 }
1027 if(ldv_irq_1_1 != 0 && line == ldv_irq_line_1_1){
1028 ldv_irq_1_1 = 0;
1029 return;
1030 }
1031 if(ldv_irq_1_2 != 0 && line == ldv_irq_line_1_2){
1032 ldv_irq_1_2 = 0;
1033 return;
1034 }
1035 if(ldv_irq_1_3 != 0 && line == ldv_irq_line_1_3){
1036 ldv_irq_1_3 = 0;
1037 return;
1038 }
1039 return;
1040 }
1041
1042
1043 int reg_check_1(irqreturn_t (*handler)(int, void *)){
1044 if(handler == wcn36xx_irq_tx_complete){
1045 return 1;
1046 }
1047 return 0;
1048 }
1049
1050
1051 void activate_suitable_irq_1(int line, void * data){
1052 if(ldv_irq_1_0 == 0){
1053 ldv_irq_line_1_0 = line;
1054 ldv_irq_data_1_0 = data;
1055 ldv_irq_1_0 = 1;
1056 return;
1057 }
1058 if(ldv_irq_1_1 == 0){
1059 ldv_irq_line_1_1 = line;
1060 ldv_irq_data_1_1 = data;
1061 ldv_irq_1_1 = 1;
1062 return;
1063 }
1064 if(ldv_irq_1_2 == 0){
1065 ldv_irq_line_1_2 = line;
1066 ldv_irq_data_1_2 = data;
1067 ldv_irq_1_2 = 1;
1068 return;
1069 }
1070 if(ldv_irq_1_3 == 0){
1071 ldv_irq_line_1_3 = line;
1072 ldv_irq_data_1_3 = data;
1073 ldv_irq_1_3 = 1;
1074 return;
1075 }
1076 return;
1077 }
1078
1079
1080 int ldv_irq_1(int state, int line, void *data){
1081 irqreturn_t irq_retval;
1082 irq_retval = __VERIFIER_nondet_int();
1083
1084 if(state != 0){
1085 switch(__VERIFIER_nondet_int()){
1086 case 0:{
1087 if(state == 1){
1088 LDV_IN_INTERRUPT=2;
1089 irq_retval = wcn36xx_irq_tx_complete(line, data);
1090 LDV_IN_INTERRUPT=1;
1091 return state;
1092 }
1093 }
1094 break;
1095 default: ldv_assume(0);
1096 }
1097 }
1098 return state;
1099 }
1100
1101
1102 int ldv_irq_2(int state, int line, void *data){
1103 irqreturn_t irq_retval;
1104 irq_retval = __VERIFIER_nondet_int();
1105
1106 if(state != 0){
1107 switch(__VERIFIER_nondet_int()){
1108 case 0:{
1109 if(state == 1){
1110 LDV_IN_INTERRUPT=2;
1111 irq_retval = wcn36xx_irq_rx_ready(line, data);
1112 LDV_IN_INTERRUPT=1;
1113 return state;
1114 }
1115 }
1116 break;
1117 default: ldv_assume(0);
1118 }
1119 }
1120 return state;
1121 }
1122
1123
1124 void choose_interrupt_1(void){
1125 switch(__VERIFIER_nondet_int()){
1126 case 0: {
1127 ldv_irq_1_0 = ldv_irq_1(ldv_irq_1_0, ldv_irq_line_1_0, ldv_irq_data_1_0);
1128 }
1129 break;
1130 case 1: {
1131 ldv_irq_1_0 = ldv_irq_1(ldv_irq_1_1, ldv_irq_line_1_1, ldv_irq_data_1_1);
1132 }
1133 break;
1134 case 2: {
1135 ldv_irq_1_0 = ldv_irq_1(ldv_irq_1_2, ldv_irq_line_1_2, ldv_irq_data_1_2);
1136 }
1137 break;
1138 case 3: {
1139 ldv_irq_1_0 = ldv_irq_1(ldv_irq_1_3, ldv_irq_line_1_3, ldv_irq_data_1_3);
1140 }
1141 break;
1142 default: ldv_assume(0);
1143 }
1144 return;
1145 }
1146
1147
1148 int reg_check_2(irqreturn_t (*handler)(int, void *)){
1149 if(handler == wcn36xx_irq_rx_ready){
1150 return 1;
1151 }
1152 return 0;
1153 } 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/module.h>
20 #include <linux/firmware.h>
21 #include <linux/platform_device.h>
22 #include "wcn36xx.h"
23
24 unsigned int wcn36xx_dbg_mask;
25 module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
26 MODULE_PARM_DESC(debug_mask, "Debugging mask");
27
28 #define CHAN2G(_freq, _idx) { \
29 .band = IEEE80211_BAND_2GHZ, \
30 .center_freq = (_freq), \
31 .hw_value = (_idx), \
32 .max_power = 25, \
33 }
34
35 #define CHAN5G(_freq, _idx) { \
36 .band = IEEE80211_BAND_5GHZ, \
37 .center_freq = (_freq), \
38 .hw_value = (_idx), \
39 .max_power = 25, \
40 }
41
42 /* The wcn firmware expects channel values to matching
43 * their mnemonic values. So use these for .hw_value. */
44 static struct ieee80211_channel wcn_2ghz_channels[] = {
45 CHAN2G(2412, 1), /* Channel 1 */
46 CHAN2G(2417, 2), /* Channel 2 */
47 CHAN2G(2422, 3), /* Channel 3 */
48 CHAN2G(2427, 4), /* Channel 4 */
49 CHAN2G(2432, 5), /* Channel 5 */
50 CHAN2G(2437, 6), /* Channel 6 */
51 CHAN2G(2442, 7), /* Channel 7 */
52 CHAN2G(2447, 8), /* Channel 8 */
53 CHAN2G(2452, 9), /* Channel 9 */
54 CHAN2G(2457, 10), /* Channel 10 */
55 CHAN2G(2462, 11), /* Channel 11 */
56 CHAN2G(2467, 12), /* Channel 12 */
57 CHAN2G(2472, 13), /* Channel 13 */
58 CHAN2G(2484, 14) /* Channel 14 */
59
60 };
61
62 static struct ieee80211_channel wcn_5ghz_channels[] = {
63 CHAN5G(5180, 36),
64 CHAN5G(5200, 40),
65 CHAN5G(5220, 44),
66 CHAN5G(5240, 48),
67 CHAN5G(5260, 52),
68 CHAN5G(5280, 56),
69 CHAN5G(5300, 60),
70 CHAN5G(5320, 64),
71 CHAN5G(5500, 100),
72 CHAN5G(5520, 104),
73 CHAN5G(5540, 108),
74 CHAN5G(5560, 112),
75 CHAN5G(5580, 116),
76 CHAN5G(5600, 120),
77 CHAN5G(5620, 124),
78 CHAN5G(5640, 128),
79 CHAN5G(5660, 132),
80 CHAN5G(5700, 140),
81 CHAN5G(5745, 149),
82 CHAN5G(5765, 153),
83 CHAN5G(5785, 157),
84 CHAN5G(5805, 161),
85 CHAN5G(5825, 165)
86 };
87
88 #define RATE(_bitrate, _hw_rate, _flags) { \
89 .bitrate = (_bitrate), \
90 .flags = (_flags), \
91 .hw_value = (_hw_rate), \
92 .hw_value_short = (_hw_rate) \
93 }
94
95 static struct ieee80211_rate wcn_2ghz_rates[] = {
96 RATE(10, HW_RATE_INDEX_1MBPS, 0),
97 RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
98 RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
99 RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
100 RATE(60, HW_RATE_INDEX_6MBPS, 0),
101 RATE(90, HW_RATE_INDEX_9MBPS, 0),
102 RATE(120, HW_RATE_INDEX_12MBPS, 0),
103 RATE(180, HW_RATE_INDEX_18MBPS, 0),
104 RATE(240, HW_RATE_INDEX_24MBPS, 0),
105 RATE(360, HW_RATE_INDEX_36MBPS, 0),
106 RATE(480, HW_RATE_INDEX_48MBPS, 0),
107 RATE(540, HW_RATE_INDEX_54MBPS, 0)
108 };
109
110 static struct ieee80211_rate wcn_5ghz_rates[] = {
111 RATE(60, HW_RATE_INDEX_6MBPS, 0),
112 RATE(90, HW_RATE_INDEX_9MBPS, 0),
113 RATE(120, HW_RATE_INDEX_12MBPS, 0),
114 RATE(180, HW_RATE_INDEX_18MBPS, 0),
115 RATE(240, HW_RATE_INDEX_24MBPS, 0),
116 RATE(360, HW_RATE_INDEX_36MBPS, 0),
117 RATE(480, HW_RATE_INDEX_48MBPS, 0),
118 RATE(540, HW_RATE_INDEX_54MBPS, 0)
119 };
120
121 static struct ieee80211_supported_band wcn_band_2ghz = {
122 .channels = wcn_2ghz_channels,
123 .n_channels = ARRAY_SIZE(wcn_2ghz_channels),
124 .bitrates = wcn_2ghz_rates,
125 .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates),
126 .ht_cap = {
127 .cap = IEEE80211_HT_CAP_GRN_FLD |
128 IEEE80211_HT_CAP_SGI_20 |
129 IEEE80211_HT_CAP_DSSSCCK40 |
130 IEEE80211_HT_CAP_LSIG_TXOP_PROT,
131 .ht_supported = true,
132 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
133 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
134 .mcs = {
135 .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
136 .rx_highest = cpu_to_le16(72),
137 .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
138 }
139 }
140 };
141
142 static struct ieee80211_supported_band wcn_band_5ghz = {
143 .channels = wcn_5ghz_channels,
144 .n_channels = ARRAY_SIZE(wcn_5ghz_channels),
145 .bitrates = wcn_5ghz_rates,
146 .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates),
147 .ht_cap = {
148 .cap = IEEE80211_HT_CAP_GRN_FLD |
149 IEEE80211_HT_CAP_SGI_20 |
150 IEEE80211_HT_CAP_DSSSCCK40 |
151 IEEE80211_HT_CAP_LSIG_TXOP_PROT |
152 IEEE80211_HT_CAP_SGI_40 |
153 IEEE80211_HT_CAP_SUP_WIDTH_20_40,
154 .ht_supported = true,
155 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
156 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
157 .mcs = {
158 .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
159 .rx_highest = cpu_to_le16(72),
160 .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
161 }
162 }
163 };
164
165 #ifdef CONFIG_PM
166
167 static const struct wiphy_wowlan_support wowlan_support = {
168 .flags = WIPHY_WOWLAN_ANY
169 };
170
171 #endif
172
173 static inline u8 get_sta_index(struct ieee80211_vif *vif,
174 struct wcn36xx_sta *sta_priv)
175 {
176 return NL80211_IFTYPE_STATION == vif->type ?
177 sta_priv->bss_sta_index :
178 sta_priv->sta_index;
179 }
180
181 static const char * const wcn36xx_caps_names[] = {
182 "MCC", /* 0 */
183 "P2P", /* 1 */
184 "DOT11AC", /* 2 */
185 "SLM_SESSIONIZATION", /* 3 */
186 "DOT11AC_OPMODE", /* 4 */
187 "SAP32STA", /* 5 */
188 "TDLS", /* 6 */
189 "P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */
190 "WLANACTIVE_OFFLOAD", /* 8 */
191 "BEACON_OFFLOAD", /* 9 */
192 "SCAN_OFFLOAD", /* 10 */
193 "ROAM_OFFLOAD", /* 11 */
194 "BCN_MISS_OFFLOAD", /* 12 */
195 "STA_POWERSAVE", /* 13 */
196 "STA_ADVANCED_PWRSAVE", /* 14 */
197 "AP_UAPSD", /* 15 */
198 "AP_DFS", /* 16 */
199 "BLOCKACK", /* 17 */
200 "PHY_ERR", /* 18 */
201 "BCN_FILTER", /* 19 */
202 "RTT", /* 20 */
203 "RATECTRL", /* 21 */
204 "WOW" /* 22 */
205 };
206
207 static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
208 {
209 if (x >= ARRAY_SIZE(wcn36xx_caps_names))
210 return "UNKNOWN";
211 return wcn36xx_caps_names[x];
212 }
213
214 static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
215 {
216 int i;
217
218 for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
219 if (get_feat_caps(wcn->fw_feat_caps, i))
220 wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i));
221 }
222 }
223
224 static void wcn36xx_detect_chip_version(struct wcn36xx *wcn)
225 {
226 if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) {
227 wcn36xx_info("Chip is 3680\n");
228 wcn->chip_version = WCN36XX_CHIP_3680;
229 } else {
230 wcn36xx_info("Chip is 3660\n");
231 wcn->chip_version = WCN36XX_CHIP_3660;
232 }
233 }
234
235 static int wcn36xx_start(struct ieee80211_hw *hw)
236 {
237 struct wcn36xx *wcn = hw->priv;
238 int ret;
239
240 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n");
241
242 /* SMD initialization */
243 ret = wcn36xx_smd_open(wcn);
244 if (ret) {
245 wcn36xx_err("Failed to open smd channel: %d\n", ret);
246 goto out_err;
247 }
248
249 /* Allocate memory pools for Mgmt BD headers and Data BD headers */
250 ret = wcn36xx_dxe_allocate_mem_pools(wcn);
251 if (ret) {
252 wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret);
253 goto out_smd_close;
254 }
255
256 ret = wcn36xx_dxe_alloc_ctl_blks(wcn);
257 if (ret) {
258 wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret);
259 goto out_free_dxe_pool;
260 }
261
262 wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
263 if (!wcn->hal_buf) {
264 wcn36xx_err("Failed to allocate smd buf\n");
265 ret = -ENOMEM;
266 goto out_free_dxe_ctl;
267 }
268
269 ret = wcn36xx_smd_load_nv(wcn);
270 if (ret) {
271 wcn36xx_err("Failed to push NV to chip\n");
272 goto out_free_smd_buf;
273 }
274
275 ret = wcn36xx_smd_start(wcn);
276 if (ret) {
277 wcn36xx_err("Failed to start chip\n");
278 goto out_free_smd_buf;
279 }
280
281 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
282 ret = wcn36xx_smd_feature_caps_exchange(wcn);
283 if (ret)
284 wcn36xx_warn("Exchange feature caps failed\n");
285 else
286 wcn36xx_feat_caps_info(wcn);
287 }
288
289 wcn36xx_detect_chip_version(wcn);
290
291 /* DMA channel initialization */
292 ret = wcn36xx_dxe_init(wcn);
293 if (ret) {
294 wcn36xx_err("DXE init failed\n");
295 goto out_smd_stop;
296 }
297
298 wcn36xx_debugfs_init(wcn);
299
300 INIT_LIST_HEAD(&wcn->vif_list);
301 spin_lock_init(&wcn->dxe_lock);
302
303 return 0;
304
305 out_smd_stop:
306 wcn36xx_smd_stop(wcn);
307 out_free_smd_buf:
308 kfree(wcn->hal_buf);
309 out_free_dxe_pool:
310 wcn36xx_dxe_free_mem_pools(wcn);
311 out_free_dxe_ctl:
312 wcn36xx_dxe_free_ctl_blks(wcn);
313 out_smd_close:
314 wcn36xx_smd_close(wcn);
315 out_err:
316 return ret;
317 }
318
319 static void wcn36xx_stop(struct ieee80211_hw *hw)
320 {
321 struct wcn36xx *wcn = hw->priv;
322
323 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n");
324
325 wcn36xx_debugfs_exit(wcn);
326 wcn36xx_smd_stop(wcn);
327 wcn36xx_dxe_deinit(wcn);
328 wcn36xx_smd_close(wcn);
329
330 wcn36xx_dxe_free_mem_pools(wcn);
331 wcn36xx_dxe_free_ctl_blks(wcn);
332
333 kfree(wcn->hal_buf);
334 }
335
336 static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
337 {
338 struct wcn36xx *wcn = hw->priv;
339 struct ieee80211_vif *vif = NULL;
340 struct wcn36xx_vif *tmp;
341
342 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
343
344 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
345 int ch = WCN36XX_HW_CHANNEL(wcn);
346 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
347 ch);
348 list_for_each_entry(tmp, &wcn->vif_list, list) {
349 vif = container_of((void *)tmp,
350 struct ieee80211_vif,
351 drv_priv);
352 wcn36xx_smd_switch_channel(wcn, vif, ch);
353 }
354 }
355
356 return 0;
357 }
358
359 #define WCN36XX_SUPPORTED_FILTERS (0)
360
361 static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
362 unsigned int changed,
363 unsigned int *total, u64 multicast)
364 {
365 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
366
367 *total &= WCN36XX_SUPPORTED_FILTERS;
368 }
369
370 static void wcn36xx_tx(struct ieee80211_hw *hw,
371 struct ieee80211_tx_control *control,
372 struct sk_buff *skb)
373 {
374 struct wcn36xx *wcn = hw->priv;
375 struct wcn36xx_sta *sta_priv = NULL;
376
377 if (control->sta)
378 sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv;
379
380 if (wcn36xx_start_tx(wcn, sta_priv, skb))
381 ieee80211_free_txskb(wcn->hw, skb);
382 }
383
384 static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
385 struct ieee80211_vif *vif,
386 struct ieee80211_sta *sta,
387 struct ieee80211_key_conf *key_conf)
388 {
389 struct wcn36xx *wcn = hw->priv;
390 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
391 struct wcn36xx_sta *sta_priv = vif_priv->sta;
392 int ret = 0;
393 u8 key[WLAN_MAX_KEY_LEN];
394
395 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n");
396 wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n",
397 cmd, key_conf->cipher, key_conf->keyidx,
398 key_conf->keylen, key_conf->flags);
399 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ",
400 key_conf->key,
401 key_conf->keylen);
402
403 switch (key_conf->cipher) {
404 case WLAN_CIPHER_SUITE_WEP40:
405 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
406 break;
407 case WLAN_CIPHER_SUITE_WEP104:
408 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
409 break;
410 case WLAN_CIPHER_SUITE_CCMP:
411 vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
412 break;
413 case WLAN_CIPHER_SUITE_TKIP:
414 vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP;
415 break;
416 default:
417 wcn36xx_err("Unsupported key type 0x%x\n",
418 key_conf->cipher);
419 ret = -EOPNOTSUPP;
420 goto out;
421 }
422
423 switch (cmd) {
424 case SET_KEY:
425 if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) {
426 /*
427 * Supplicant is sending key in the wrong order:
428 * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b)
429 * but HW expects it to be in the order as described in
430 * IEEE 802.11 spec (see chapter 11.7) like this:
431 * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b)
432 */
433 memcpy(key, key_conf->key, 16);
434 memcpy(key + 16, key_conf->key + 24, 8);
435 memcpy(key + 24, key_conf->key + 16, 8);
436 } else {
437 memcpy(key, key_conf->key, key_conf->keylen);
438 }
439
440 if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
441 sta_priv->is_data_encrypted = true;
442 /* Reconfigure bss with encrypt_type */
443 if (NL80211_IFTYPE_STATION == vif->type)
444 wcn36xx_smd_config_bss(wcn,
445 vif,
446 sta,
447 sta->addr,
448 true);
449
450 wcn36xx_smd_set_stakey(wcn,
451 vif_priv->encrypt_type,
452 key_conf->keyidx,
453 key_conf->keylen,
454 key,
455 get_sta_index(vif, sta_priv));
456 } else {
457 wcn36xx_smd_set_bsskey(wcn,
458 vif_priv->encrypt_type,
459 key_conf->keyidx,
460 key_conf->keylen,
461 key);
462 if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
463 (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
464 sta_priv->is_data_encrypted = true;
465 wcn36xx_smd_set_stakey(wcn,
466 vif_priv->encrypt_type,
467 key_conf->keyidx,
468 key_conf->keylen,
469 key,
470 get_sta_index(vif, sta_priv));
471 }
472 }
473 break;
474 case DISABLE_KEY:
475 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
476 wcn36xx_smd_remove_bsskey(wcn,
477 vif_priv->encrypt_type,
478 key_conf->keyidx);
479 } else {
480 sta_priv->is_data_encrypted = false;
481 /* do not remove key if disassociated */
482 if (sta_priv->aid)
483 wcn36xx_smd_remove_stakey(wcn,
484 vif_priv->encrypt_type,
485 key_conf->keyidx,
486 get_sta_index(vif, sta_priv));
487 }
488 break;
489 default:
490 wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
491 ret = -EOPNOTSUPP;
492 goto out;
493 }
494
495 out:
496 return ret;
497 }
498
499 static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
500 struct ieee80211_vif *vif,
501 const u8 *mac_addr)
502 {
503 struct wcn36xx *wcn = hw->priv;
504
505 wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
506 wcn36xx_smd_start_scan(wcn);
507 }
508
509 static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
510 struct ieee80211_vif *vif)
511 {
512 struct wcn36xx *wcn = hw->priv;
513
514 wcn36xx_smd_end_scan(wcn);
515 wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
516 }
517
518 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
519 enum ieee80211_band band)
520 {
521 int i, size;
522 u16 *rates_table;
523 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
524 u32 rates = sta->supp_rates[band];
525
526 memset(&sta_priv->supported_rates, 0,
527 sizeof(sta_priv->supported_rates));
528 sta_priv->supported_rates.op_rate_mode = STA_11n;
529
530 size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates);
531 rates_table = sta_priv->supported_rates.dsss_rates;
532 if (band == IEEE80211_BAND_2GHZ) {
533 for (i = 0; i < size; i++) {
534 if (rates & 0x01) {
535 rates_table[i] = wcn_2ghz_rates[i].hw_value;
536 rates = rates >> 1;
537 }
538 }
539 }
540
541 size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates);
542 rates_table = sta_priv->supported_rates.ofdm_rates;
543 for (i = 0; i < size; i++) {
544 if (rates & 0x01) {
545 rates_table[i] = wcn_5ghz_rates[i].hw_value;
546 rates = rates >> 1;
547 }
548 }
549
550 if (sta->ht_cap.ht_supported) {
551 BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) >
552 sizeof(sta_priv->supported_rates.supported_mcs_set));
553 memcpy(sta_priv->supported_rates.supported_mcs_set,
554 sta->ht_cap.mcs.rx_mask,
555 sizeof(sta->ht_cap.mcs.rx_mask));
556 }
557 }
558 void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
559 {
560 u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = {
561 HW_RATE_INDEX_6MBPS,
562 HW_RATE_INDEX_9MBPS,
563 HW_RATE_INDEX_12MBPS,
564 HW_RATE_INDEX_18MBPS,
565 HW_RATE_INDEX_24MBPS,
566 HW_RATE_INDEX_36MBPS,
567 HW_RATE_INDEX_48MBPS,
568 HW_RATE_INDEX_54MBPS
569 };
570 u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = {
571 HW_RATE_INDEX_1MBPS,
572 HW_RATE_INDEX_2MBPS,
573 HW_RATE_INDEX_5_5MBPS,
574 HW_RATE_INDEX_11MBPS
575 };
576
577 rates->op_rate_mode = STA_11n;
578 memcpy(rates->dsss_rates, dsss_rates,
579 sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES);
580 memcpy(rates->ofdm_rates, ofdm_rates,
581 sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES);
582 rates->supported_mcs_set[0] = 0xFF;
583 }
584 static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
585 struct ieee80211_vif *vif,
586 struct ieee80211_bss_conf *bss_conf,
587 u32 changed)
588 {
589 struct wcn36xx *wcn = hw->priv;
590 struct sk_buff *skb = NULL;
591 u16 tim_off, tim_len;
592 enum wcn36xx_hal_link_state link_state;
593 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
594
595 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
596 vif, changed);
597
598 if (changed & BSS_CHANGED_BEACON_INFO) {
599 wcn36xx_dbg(WCN36XX_DBG_MAC,
600 "mac bss changed dtim period %d\n",
601 bss_conf->dtim_period);
602
603 vif_priv->dtim_period = bss_conf->dtim_period;
604 }
605
606 if (changed & BSS_CHANGED_PS) {
607 wcn36xx_dbg(WCN36XX_DBG_MAC,
608 "mac bss PS set %d\n",
609 bss_conf->ps);
610 if (bss_conf->ps) {
611 wcn36xx_pmc_enter_bmps_state(wcn, vif);
612 } else {
613 wcn36xx_pmc_exit_bmps_state(wcn, vif);
614 }
615 }
616
617 if (changed & BSS_CHANGED_BSSID) {
618 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
619 bss_conf->bssid);
620
621 if (!is_zero_ether_addr(bss_conf->bssid)) {
622 vif_priv->is_joining = true;
623 vif_priv->bss_index = 0xff;
624 wcn36xx_smd_join(wcn, bss_conf->bssid,
625 vif->addr, WCN36XX_HW_CHANNEL(wcn));
626 wcn36xx_smd_config_bss(wcn, vif, NULL,
627 bss_conf->bssid, false);
628 } else {
629 vif_priv->is_joining = false;
630 wcn36xx_smd_delete_bss(wcn, vif);
631 }
632 }
633
634 if (changed & BSS_CHANGED_SSID) {
635 wcn36xx_dbg(WCN36XX_DBG_MAC,
636 "mac bss changed ssid\n");
637 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ",
638 bss_conf->ssid, bss_conf->ssid_len);
639
640 vif_priv->ssid.length = bss_conf->ssid_len;
641 memcpy(&vif_priv->ssid.ssid,
642 bss_conf->ssid,
643 bss_conf->ssid_len);
644 }
645
646 if (changed & BSS_CHANGED_ASSOC) {
647 vif_priv->is_joining = false;
648 if (bss_conf->assoc) {
649 struct ieee80211_sta *sta;
650 struct wcn36xx_sta *sta_priv;
651
652 wcn36xx_dbg(WCN36XX_DBG_MAC,
653 "mac assoc bss %pM vif %pM AID=%d\n",
654 bss_conf->bssid,
655 vif->addr,
656 bss_conf->aid);
657
658 rcu_read_lock();
659 sta = ieee80211_find_sta(vif, bss_conf->bssid);
660 if (!sta) {
661 wcn36xx_err("sta %pM is not found\n",
662 bss_conf->bssid);
663 rcu_read_unlock();
664 goto out;
665 }
666 sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
667
668 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
669
670 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid,
671 vif->addr,
672 WCN36XX_HAL_LINK_POSTASSOC_STATE);
673 wcn36xx_smd_config_bss(wcn, vif, sta,
674 bss_conf->bssid,
675 true);
676 sta_priv->aid = bss_conf->aid;
677 /*
678 * config_sta must be called from because this is the
679 * place where AID is available.
680 */
681 wcn36xx_smd_config_sta(wcn, vif, sta);
682 rcu_read_unlock();
683 } else {
684 wcn36xx_dbg(WCN36XX_DBG_MAC,
685 "disassociated bss %pM vif %pM AID=%d\n",
686 bss_conf->bssid,
687 vif->addr,
688 bss_conf->aid);
689 wcn36xx_smd_set_link_st(wcn,
690 bss_conf->bssid,
691 vif->addr,
692 WCN36XX_HAL_LINK_IDLE_STATE);
693 }
694 }
695
696 if (changed & BSS_CHANGED_AP_PROBE_RESP) {
697 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n");
698 skb = ieee80211_proberesp_get(hw, vif);
699 if (!skb) {
700 wcn36xx_err("failed to alloc probereq skb\n");
701 goto out;
702 }
703
704 wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb);
705 dev_kfree_skb(skb);
706 }
707
708 if (changed & BSS_CHANGED_BEACON_ENABLED ||
709 changed & BSS_CHANGED_BEACON) {
710 wcn36xx_dbg(WCN36XX_DBG_MAC,
711 "mac bss changed beacon enabled %d\n",
712 bss_conf->enable_beacon);
713
714 if (bss_conf->enable_beacon) {
715 vif_priv->dtim_period = bss_conf->dtim_period;
716 vif_priv->bss_index = 0xff;
717 wcn36xx_smd_config_bss(wcn, vif, NULL,
718 vif->addr, false);
719 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
720 &tim_len);
721 if (!skb) {
722 wcn36xx_err("failed to alloc beacon skb\n");
723 goto out;
724 }
725 wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0);
726 dev_kfree_skb(skb);
727
728 if (vif->type == NL80211_IFTYPE_ADHOC ||
729 vif->type == NL80211_IFTYPE_MESH_POINT)
730 link_state = WCN36XX_HAL_LINK_IBSS_STATE;
731 else
732 link_state = WCN36XX_HAL_LINK_AP_STATE;
733
734 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
735 link_state);
736 } else {
737 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
738 WCN36XX_HAL_LINK_IDLE_STATE);
739 wcn36xx_smd_delete_bss(wcn, vif);
740 }
741 }
742 out:
743 return;
744 }
745
746 /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */
747 static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
748 {
749 struct wcn36xx *wcn = hw->priv;
750 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
751
752 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
753 return 0;
754 }
755
756 static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
757 struct ieee80211_vif *vif)
758 {
759 struct wcn36xx *wcn = hw->priv;
760 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
761 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
762
763 list_del(&vif_priv->list);
764 wcn36xx_smd_delete_sta_self(wcn, vif->addr);
765 }
766
767 static int wcn36xx_add_interface(struct ieee80211_hw *hw,
768 struct ieee80211_vif *vif)
769 {
770 struct wcn36xx *wcn = hw->priv;
771 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
772
773 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
774 vif, vif->type);
775
776 if (!(NL80211_IFTYPE_STATION == vif->type ||
777 NL80211_IFTYPE_AP == vif->type ||
778 NL80211_IFTYPE_ADHOC == vif->type ||
779 NL80211_IFTYPE_MESH_POINT == vif->type)) {
780 wcn36xx_warn("Unsupported interface type requested: %d\n",
781 vif->type);
782 return -EOPNOTSUPP;
783 }
784
785 list_add(&vif_priv->list, &wcn->vif_list);
786 wcn36xx_smd_add_sta_self(wcn, vif);
787
788 return 0;
789 }
790
791 static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
792 struct ieee80211_sta *sta)
793 {
794 struct wcn36xx *wcn = hw->priv;
795 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
796 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
797 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
798 vif, sta->addr);
799
800 spin_lock_init(&sta_priv->ampdu_lock);
801 vif_priv->sta = sta_priv;
802 sta_priv->vif = vif_priv;
803 /*
804 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
805 * at this stage AID is not available yet.
806 */
807 if (NL80211_IFTYPE_STATION != vif->type) {
808 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
809 sta_priv->aid = sta->aid;
810 wcn36xx_smd_config_sta(wcn, vif, sta);
811 }
812 return 0;
813 }
814
815 static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
816 struct ieee80211_vif *vif,
817 struct ieee80211_sta *sta)
818 {
819 struct wcn36xx *wcn = hw->priv;
820 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
821 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
822
823 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
824 vif, sta->addr, sta_priv->sta_index);
825
826 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
827 vif_priv->sta = NULL;
828 sta_priv->vif = NULL;
829 return 0;
830 }
831
832 #ifdef CONFIG_PM
833
834 static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
835 {
836 struct wcn36xx *wcn = hw->priv;
837
838 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n");
839
840 flush_workqueue(wcn->hal_ind_wq);
841 wcn36xx_smd_set_power_params(wcn, true);
842 return 0;
843 }
844
845 static int wcn36xx_resume(struct ieee80211_hw *hw)
846 {
847 struct wcn36xx *wcn = hw->priv;
848
849 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n");
850
851 flush_workqueue(wcn->hal_ind_wq);
852 wcn36xx_smd_set_power_params(wcn, false);
853 return 0;
854 }
855
856 #endif
857
858 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
859 struct ieee80211_vif *vif,
860 enum ieee80211_ampdu_mlme_action action,
861 struct ieee80211_sta *sta, u16 tid, u16 *ssn,
862 u8 buf_size, bool amsdu)
863 {
864 struct wcn36xx *wcn = hw->priv;
865 struct wcn36xx_sta *sta_priv = NULL;
866
867 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
868 action, tid);
869
870 sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
871
872 switch (action) {
873 case IEEE80211_AMPDU_RX_START:
874 sta_priv->tid = tid;
875 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
876 get_sta_index(vif, sta_priv));
877 wcn36xx_smd_add_ba(wcn);
878 wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv));
879 break;
880 case IEEE80211_AMPDU_RX_STOP:
881 wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv));
882 break;
883 case IEEE80211_AMPDU_TX_START:
884 spin_lock_bh(&sta_priv->ampdu_lock);
885 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
886 spin_unlock_bh(&sta_priv->ampdu_lock);
887
888 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
889 break;
890 case IEEE80211_AMPDU_TX_OPERATIONAL:
891 spin_lock_bh(&sta_priv->ampdu_lock);
892 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
893 spin_unlock_bh(&sta_priv->ampdu_lock);
894
895 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
896 get_sta_index(vif, sta_priv));
897 break;
898 case IEEE80211_AMPDU_TX_STOP_FLUSH:
899 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
900 case IEEE80211_AMPDU_TX_STOP_CONT:
901 spin_lock_bh(&sta_priv->ampdu_lock);
902 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE;
903 spin_unlock_bh(&sta_priv->ampdu_lock);
904
905 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
906 break;
907 default:
908 wcn36xx_err("Unknown AMPDU action\n");
909 }
910
911 return 0;
912 }
913
914 static const struct ieee80211_ops wcn36xx_ops = {
915 .start = wcn36xx_start,
916 .stop = wcn36xx_stop,
917 .add_interface = wcn36xx_add_interface,
918 .remove_interface = wcn36xx_remove_interface,
919 #ifdef CONFIG_PM
920 .suspend = wcn36xx_suspend,
921 .resume = wcn36xx_resume,
922 #endif
923 .config = wcn36xx_config,
924 .configure_filter = wcn36xx_configure_filter,
925 .tx = wcn36xx_tx,
926 .set_key = wcn36xx_set_key,
927 .sw_scan_start = wcn36xx_sw_scan_start,
928 .sw_scan_complete = wcn36xx_sw_scan_complete,
929 .bss_info_changed = wcn36xx_bss_info_changed,
930 .set_rts_threshold = wcn36xx_set_rts_threshold,
931 .sta_add = wcn36xx_sta_add,
932 .sta_remove = wcn36xx_sta_remove,
933 .ampdu_action = wcn36xx_ampdu_action,
934 };
935
936 static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
937 {
938 int ret = 0;
939
940 static const u32 cipher_suites[] = {
941 WLAN_CIPHER_SUITE_WEP40,
942 WLAN_CIPHER_SUITE_WEP104,
943 WLAN_CIPHER_SUITE_TKIP,
944 WLAN_CIPHER_SUITE_CCMP,
945 };
946
947 ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY);
948 ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION);
949 ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR);
950 ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
951 ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
952 ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
953
954 wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
955 BIT(NL80211_IFTYPE_AP) |
956 BIT(NL80211_IFTYPE_ADHOC) |
957 BIT(NL80211_IFTYPE_MESH_POINT);
958
959 wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz;
960 wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz;
961
962 wcn->hw->wiphy->cipher_suites = cipher_suites;
963 wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
964
965 wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
966
967 #ifdef CONFIG_PM
968 wcn->hw->wiphy->wowlan = &wowlan_support;
969 #endif
970
971 wcn->hw->max_listen_interval = 200;
972
973 wcn->hw->queues = 4;
974
975 SET_IEEE80211_DEV(wcn->hw, wcn->dev);
976
977 wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta);
978 wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif);
979
980 return ret;
981 }
982
983 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
984 struct platform_device *pdev)
985 {
986 struct resource *res;
987 /* Set TX IRQ */
988 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
989 "wcnss_wlantx_irq");
990 if (!res) {
991 wcn36xx_err("failed to get tx_irq\n");
992 return -ENOENT;
993 }
994 wcn->tx_irq = res->start;
995
996 /* Set RX IRQ */
997 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
998 "wcnss_wlanrx_irq");
999 if (!res) {
1000 wcn36xx_err("failed to get rx_irq\n");
1001 return -ENOENT;
1002 }
1003 wcn->rx_irq = res->start;
1004
1005 /* Map the memory */
1006 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1007 "wcnss_mmio");
1008 if (!res) {
1009 wcn36xx_err("failed to get mmio\n");
1010 return -ENOENT;
1011 }
1012 wcn->mmio = ioremap(res->start, resource_size(res));
1013 if (!wcn->mmio) {
1014 wcn36xx_err("failed to map io memory\n");
1015 return -ENOMEM;
1016 }
1017 return 0;
1018 }
1019
1020 static int wcn36xx_probe(struct platform_device *pdev)
1021 {
1022 struct ieee80211_hw *hw;
1023 struct wcn36xx *wcn;
1024 int ret;
1025 u8 addr[ETH_ALEN];
1026
1027 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
1028
1029 hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
1030 if (!hw) {
1031 wcn36xx_err("failed to alloc hw\n");
1032 ret = -ENOMEM;
1033 goto out_err;
1034 }
1035 platform_set_drvdata(pdev, hw);
1036 wcn = hw->priv;
1037 wcn->hw = hw;
1038 wcn->dev = &pdev->dev;
1039 wcn->ctrl_ops = pdev->dev.platform_data;
1040
1041 mutex_init(&wcn->hal_mutex);
1042
1043 if (!wcn->ctrl_ops->get_hw_mac(addr)) {
1044 wcn36xx_info("mac address: %pM\n", addr);
1045 SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
1046 }
1047
1048 ret = wcn36xx_platform_get_resources(wcn, pdev);
1049 if (ret)
1050 goto out_wq;
1051
1052 wcn36xx_init_ieee80211(wcn);
1053 ret = ieee80211_register_hw(wcn->hw);
1054 if (ret)
1055 goto out_unmap;
1056
1057 return 0;
1058
1059 out_unmap:
1060 iounmap(wcn->mmio);
1061 out_wq:
1062 ieee80211_free_hw(hw);
1063 out_err:
1064 return ret;
1065 }
1066 static int wcn36xx_remove(struct platform_device *pdev)
1067 {
1068 struct ieee80211_hw *hw = platform_get_drvdata(pdev);
1069 struct wcn36xx *wcn = hw->priv;
1070 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
1071
1072 release_firmware(wcn->nv);
1073 mutex_destroy(&wcn->hal_mutex);
1074
1075 ieee80211_unregister_hw(hw);
1076 iounmap(wcn->mmio);
1077 ieee80211_free_hw(hw);
1078
1079 return 0;
1080 }
1081 static const struct platform_device_id wcn36xx_platform_id_table[] = {
1082 {
1083 .name = "wcn36xx",
1084 .driver_data = 0
1085 },
1086 {}
1087 };
1088 MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
1089
1090 static struct platform_driver wcn36xx_driver = {
1091 .probe = wcn36xx_probe,
1092 .remove = wcn36xx_remove,
1093 .driver = {
1094 .name = "wcn36xx",
1095 },
1096 .id_table = wcn36xx_platform_id_table,
1097 };
1098
1099 static int __init wcn36xx_init(void)
1100 {
1101 platform_driver_register(&wcn36xx_driver);
1102 return 0;
1103 }
1104 module_init(wcn36xx_init);
1105
1106 static void __exit wcn36xx_exit(void)
1107 {
1108 platform_driver_unregister(&wcn36xx_driver);
1109 }
1110 module_exit(wcn36xx_exit);
1111
1112 MODULE_LICENSE("Dual BSD/GPL");
1113 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
1114 MODULE_FIRMWARE(WLAN_NV_FILE); 1
2 #include <linux/kernel.h>
3 #include <linux/mutex.h>
4 #include <linux/spinlock.h>
5 #include <linux/errno.h>
6 #include <verifier/rcv.h>
7 #include <linux/list.h>
8
9 /* mutexes */
10 extern int mutex_lock_interruptible(struct mutex *lock);
11 extern int mutex_lock_killable(struct mutex *lock);
12 extern void mutex_lock(struct mutex *lock);
13
14 /* mutex model functions */
15 extern void ldv_mutex_lock(struct mutex *lock, char *sign);
16 extern int ldv_mutex_is_locked(struct mutex *lock, char *sign);
17 extern void ldv_mutex_unlock(struct mutex *lock, char *sign);
18
19
20 /* Spin locks */
21 extern void __ldv_spin_lock(spinlock_t *lock);
22 extern void __ldv_spin_unlock(spinlock_t *lock);
23 extern int __ldv_spin_trylock(spinlock_t *lock);
24 extern void __ldv_spin_unlock_wait(spinlock_t *lock);
25 extern void __ldv_spin_can_lock(spinlock_t *lock);
26 extern int __ldv_atomic_dec_and_lock(spinlock_t *lock);
27
28 /* spin model functions */
29 extern void ldv_spin_lock(spinlock_t *lock, char *sign);
30 extern void ldv_spin_unlock(spinlock_t *lock, char *sign);
31 extern int ldv_spin_is_locked(spinlock_t *lock, char *sign);
32
33 /* Support for list binder functions */
34 static inline struct list_head *ldv_list_get_first(struct list_head *head) {
35 return head->next;
36 }
37
38 static inline int ldv_list_is_stop(struct list_head *pos, struct list_head *head) {
39 return pos==head;
40 }
41
42 static inline struct list_head *ldv_list_get_next(struct list_head *pos) {
43 return pos->next;
44 }
45
46 #include <linux/mutex.h>
47 #include <linux/slab.h>
48 #include <linux/irqreturn.h>
49 #include <verifier/rcv.h>
50 #include <linux/rtnetlink.h>
51 #include <linux/gfp.h>
52 void* ldv_irq_data_2_1;
53 int ldv_irq_1_3=0;
54 int ldv_irq_line_2_2;
55 void* ldv_irq_data_1_1;
56 int ldv_irq_1_0=0;
57 int probed_5=0;
58 struct file *fops_wcn36xx_bmps_group2;
59 int ldv_state_variable_6;
60 void* ldv_irq_data_1_0;
61 int ldv_state_variable_0;
62 int ldv_state_variable_5;
63 int ldv_irq_line_2_1;
64 int ldv_state_variable_2;
65 int ldv_irq_2_0=0;
66 void* ldv_irq_data_1_3;
67 void* ldv_irq_data_1_2;
68 struct file *fops_wcn36xx_dump_group2;
69 void* ldv_irq_data_2_0;
70 struct inode *fops_wcn36xx_dump_group1;
71 int ldv_irq_1_2=0;
72 int LDV_IN_INTERRUPT = 1;
73 int ldv_irq_1_1=0;
74 int __VERIFIER_nondet_int(void);
75 int ldv_irq_2_3=0;
76 void* ldv_irq_data_2_3;
77 int ldv_irq_line_1_3;
78 int ldv_irq_2_2=0;
79 struct mutex fs_mutex;
80 int ldv_irq_line_2_0;
81 int ldv_state_variable_3;
82 int ldv_irq_line_1_0;
83 struct platform_device *wcn36xx_driver_group1;
84 struct mutex ar_mutex;
85 int ref_cnt;
86 struct mutex key_mtx;
87 int ldv_irq_line_1_1;
88 void* ldv_irq_data_2_2;
89 struct ieee80211_hw *wcn36xx_ops_group0;
90 int ldv_state_variable_1;
91 struct inode *fops_wcn36xx_bmps_group1;
92 int ldv_irq_line_1_2;
93 int ldv_state_variable_4;
94 int ldv_irq_line_2_3;
95 int ldv_irq_2_1=0;
96 void ldv_initialyze_ieee80211_ops_6(void);
97 int evil_hack_key_6(void);
98 void ldv_file_operations_3(void);
99 void choose_interrupt_2(void);
100 void disable_suitable_irq_2(int line, void * data);
101 int evil_hack_6(void);
102 void ldv_platform_probe_5(int (*probe)(struct platform_device *));
103 void activate_suitable_irq_2(int line, void * data);
104 void disable_suitable_irq_1(int line, void * data);
105 int reg_check_1(irqreturn_t (*handler)(int, void *));
106 void activate_suitable_irq_1(int line, void * data);
107 int ldv_irq_1(int state, int line, void *data);
108 int evil_hack_fs_lock(void);
109 int __VERIFIER_nondet_int(void);
110 void ldv_platform_driver_init_5(void);
111 int ldv_irq_2(int state, int line, void *data);
112 int evil_hack_ar_lock(void);
113 void choose_interrupt_1(void);
114 int reg_check_2(irqreturn_t (*handler)(int, void *));
115 void ldv_file_operations_4(void);
116 #line 1 "/work/ldvuser/andrianov/work/current--X--drivers/net/wireless/ath/wcn36xx/--X--defaultlinux-4.5-rc7--X--races--X--cpachecker/linux-4.5-rc7/csd_deg_dscv/19/dscv_tempdir/dscv/ri/races/drivers/net/wireless/ath/wcn36xx/main.c"
117 /*
118 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
119 *
120 * Permission to use, copy, modify, and/or distribute this software for any
121 * purpose with or without fee is hereby granted, provided that the above
122 * copyright notice and this permission notice appear in all copies.
123 *
124 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
125 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
126 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
127 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
128 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
129 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
130 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
131 */
132
133 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
134
135 #include <linux/module.h>
136 #include <linux/firmware.h>
137 #include <linux/platform_device.h>
138 #include "wcn36xx.h"
139
140 unsigned int wcn36xx_dbg_mask;
141 module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
142 MODULE_PARM_DESC(debug_mask, "Debugging mask");
143
144 #define CHAN2G(_freq, _idx) { \
145 .band = IEEE80211_BAND_2GHZ, \
146 .center_freq = (_freq), \
147 .hw_value = (_idx), \
148 .max_power = 25, \
149 }
150
151 #define CHAN5G(_freq, _idx) { \
152 .band = IEEE80211_BAND_5GHZ, \
153 .center_freq = (_freq), \
154 .hw_value = (_idx), \
155 .max_power = 25, \
156 }
157
158 /* The wcn firmware expects channel values to matching
159 * their mnemonic values. So use these for .hw_value. */
160 static struct ieee80211_channel wcn_2ghz_channels[] = {
161 CHAN2G(2412, 1), /* Channel 1 */
162 CHAN2G(2417, 2), /* Channel 2 */
163 CHAN2G(2422, 3), /* Channel 3 */
164 CHAN2G(2427, 4), /* Channel 4 */
165 CHAN2G(2432, 5), /* Channel 5 */
166 CHAN2G(2437, 6), /* Channel 6 */
167 CHAN2G(2442, 7), /* Channel 7 */
168 CHAN2G(2447, 8), /* Channel 8 */
169 CHAN2G(2452, 9), /* Channel 9 */
170 CHAN2G(2457, 10), /* Channel 10 */
171 CHAN2G(2462, 11), /* Channel 11 */
172 CHAN2G(2467, 12), /* Channel 12 */
173 CHAN2G(2472, 13), /* Channel 13 */
174 CHAN2G(2484, 14) /* Channel 14 */
175
176 };
177
178 static struct ieee80211_channel wcn_5ghz_channels[] = {
179 CHAN5G(5180, 36),
180 CHAN5G(5200, 40),
181 CHAN5G(5220, 44),
182 CHAN5G(5240, 48),
183 CHAN5G(5260, 52),
184 CHAN5G(5280, 56),
185 CHAN5G(5300, 60),
186 CHAN5G(5320, 64),
187 CHAN5G(5500, 100),
188 CHAN5G(5520, 104),
189 CHAN5G(5540, 108),
190 CHAN5G(5560, 112),
191 CHAN5G(5580, 116),
192 CHAN5G(5600, 120),
193 CHAN5G(5620, 124),
194 CHAN5G(5640, 128),
195 CHAN5G(5660, 132),
196 CHAN5G(5700, 140),
197 CHAN5G(5745, 149),
198 CHAN5G(5765, 153),
199 CHAN5G(5785, 157),
200 CHAN5G(5805, 161),
201 CHAN5G(5825, 165)
202 };
203
204 #define RATE(_bitrate, _hw_rate, _flags) { \
205 .bitrate = (_bitrate), \
206 .flags = (_flags), \
207 .hw_value = (_hw_rate), \
208 .hw_value_short = (_hw_rate) \
209 }
210
211 static struct ieee80211_rate wcn_2ghz_rates[] = {
212 RATE(10, HW_RATE_INDEX_1MBPS, 0),
213 RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
214 RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
215 RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
216 RATE(60, HW_RATE_INDEX_6MBPS, 0),
217 RATE(90, HW_RATE_INDEX_9MBPS, 0),
218 RATE(120, HW_RATE_INDEX_12MBPS, 0),
219 RATE(180, HW_RATE_INDEX_18MBPS, 0),
220 RATE(240, HW_RATE_INDEX_24MBPS, 0),
221 RATE(360, HW_RATE_INDEX_36MBPS, 0),
222 RATE(480, HW_RATE_INDEX_48MBPS, 0),
223 RATE(540, HW_RATE_INDEX_54MBPS, 0)
224 };
225
226 static struct ieee80211_rate wcn_5ghz_rates[] = {
227 RATE(60, HW_RATE_INDEX_6MBPS, 0),
228 RATE(90, HW_RATE_INDEX_9MBPS, 0),
229 RATE(120, HW_RATE_INDEX_12MBPS, 0),
230 RATE(180, HW_RATE_INDEX_18MBPS, 0),
231 RATE(240, HW_RATE_INDEX_24MBPS, 0),
232 RATE(360, HW_RATE_INDEX_36MBPS, 0),
233 RATE(480, HW_RATE_INDEX_48MBPS, 0),
234 RATE(540, HW_RATE_INDEX_54MBPS, 0)
235 };
236
237 static struct ieee80211_supported_band wcn_band_2ghz = {
238 .channels = wcn_2ghz_channels,
239 .n_channels = ARRAY_SIZE(wcn_2ghz_channels),
240 .bitrates = wcn_2ghz_rates,
241 .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates),
242 .ht_cap = {
243 .cap = IEEE80211_HT_CAP_GRN_FLD |
244 IEEE80211_HT_CAP_SGI_20 |
245 IEEE80211_HT_CAP_DSSSCCK40 |
246 IEEE80211_HT_CAP_LSIG_TXOP_PROT,
247 .ht_supported = true,
248 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
249 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
250 .mcs = {
251 .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
252 .rx_highest = cpu_to_le16(72),
253 .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
254 }
255 }
256 };
257
258 static struct ieee80211_supported_band wcn_band_5ghz = {
259 .channels = wcn_5ghz_channels,
260 .n_channels = ARRAY_SIZE(wcn_5ghz_channels),
261 .bitrates = wcn_5ghz_rates,
262 .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates),
263 .ht_cap = {
264 .cap = IEEE80211_HT_CAP_GRN_FLD |
265 IEEE80211_HT_CAP_SGI_20 |
266 IEEE80211_HT_CAP_DSSSCCK40 |
267 IEEE80211_HT_CAP_LSIG_TXOP_PROT |
268 IEEE80211_HT_CAP_SGI_40 |
269 IEEE80211_HT_CAP_SUP_WIDTH_20_40,
270 .ht_supported = true,
271 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
272 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
273 .mcs = {
274 .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
275 .rx_highest = cpu_to_le16(72),
276 .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
277 }
278 }
279 };
280
281 #ifdef CONFIG_PM
282
283 static const struct wiphy_wowlan_support wowlan_support = {
284 .flags = WIPHY_WOWLAN_ANY
285 };
286
287 #endif
288
289 static inline u8 get_sta_index(struct ieee80211_vif *vif,
290 struct wcn36xx_sta *sta_priv)
291 {
292 return NL80211_IFTYPE_STATION == vif->type ?
293 sta_priv->bss_sta_index :
294 sta_priv->sta_index;
295 }
296
297 static const char * const wcn36xx_caps_names[] = {
298 "MCC", /* 0 */
299 "P2P", /* 1 */
300 "DOT11AC", /* 2 */
301 "SLM_SESSIONIZATION", /* 3 */
302 "DOT11AC_OPMODE", /* 4 */
303 "SAP32STA", /* 5 */
304 "TDLS", /* 6 */
305 "P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */
306 "WLANACTIVE_OFFLOAD", /* 8 */
307 "BEACON_OFFLOAD", /* 9 */
308 "SCAN_OFFLOAD", /* 10 */
309 "ROAM_OFFLOAD", /* 11 */
310 "BCN_MISS_OFFLOAD", /* 12 */
311 "STA_POWERSAVE", /* 13 */
312 "STA_ADVANCED_PWRSAVE", /* 14 */
313 "AP_UAPSD", /* 15 */
314 "AP_DFS", /* 16 */
315 "BLOCKACK", /* 17 */
316 "PHY_ERR", /* 18 */
317 "BCN_FILTER", /* 19 */
318 "RTT", /* 20 */
319 "RATECTRL", /* 21 */
320 "WOW" /* 22 */
321 };
322
323 static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
324 {
325 if (x >= ARRAY_SIZE(wcn36xx_caps_names))
326 return "UNKNOWN";
327 return wcn36xx_caps_names[x];
328 }
329
330 static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
331 {
332 int i;
333
334 for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
335 if (get_feat_caps(wcn->fw_feat_caps, i))
336 wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i));
337 }
338 }
339
340 static void wcn36xx_detect_chip_version(struct wcn36xx *wcn)
341 {
342 if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) {
343 wcn36xx_info("Chip is 3680\n");
344 wcn->chip_version = WCN36XX_CHIP_3680;
345 } else {
346 wcn36xx_info("Chip is 3660\n");
347 wcn->chip_version = WCN36XX_CHIP_3660;
348 }
349 }
350
351 static int wcn36xx_start(struct ieee80211_hw *hw)
352 {
353 struct wcn36xx *wcn = hw->priv;
354 int ret;
355
356 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n");
357
358 /* SMD initialization */
359 ret = wcn36xx_smd_open(wcn);
360 if (ret) {
361 wcn36xx_err("Failed to open smd channel: %d\n", ret);
362 goto out_err;
363 }
364
365 /* Allocate memory pools for Mgmt BD headers and Data BD headers */
366 ret = wcn36xx_dxe_allocate_mem_pools(wcn);
367 if (ret) {
368 wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret);
369 goto out_smd_close;
370 }
371
372 ret = wcn36xx_dxe_alloc_ctl_blks(wcn);
373 if (ret) {
374 wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret);
375 goto out_free_dxe_pool;
376 }
377
378 wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
379 if (!wcn->hal_buf) {
380 wcn36xx_err("Failed to allocate smd buf\n");
381 ret = -ENOMEM;
382 goto out_free_dxe_ctl;
383 }
384
385 ret = wcn36xx_smd_load_nv(wcn);
386 if (ret) {
387 wcn36xx_err("Failed to push NV to chip\n");
388 goto out_free_smd_buf;
389 }
390
391 ret = wcn36xx_smd_start(wcn);
392 if (ret) {
393 wcn36xx_err("Failed to start chip\n");
394 goto out_free_smd_buf;
395 }
396
397 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
398 ret = wcn36xx_smd_feature_caps_exchange(wcn);
399 if (ret)
400 wcn36xx_warn("Exchange feature caps failed\n");
401 else
402 wcn36xx_feat_caps_info(wcn);
403 }
404
405 wcn36xx_detect_chip_version(wcn);
406
407 /* DMA channel initialization */
408 ret = wcn36xx_dxe_init(wcn);
409 if (ret) {
410 wcn36xx_err("DXE init failed\n");
411 goto out_smd_stop;
412 }
413
414 wcn36xx_debugfs_init(wcn);
415
416 INIT_LIST_HEAD(&wcn->vif_list);
417 spin_lock_init(&wcn->dxe_lock);
418
419 return 0;
420
421 out_smd_stop:
422 wcn36xx_smd_stop(wcn);
423 out_free_smd_buf:
424 kfree(wcn->hal_buf);
425 out_free_dxe_pool:
426 wcn36xx_dxe_free_mem_pools(wcn);
427 out_free_dxe_ctl:
428 wcn36xx_dxe_free_ctl_blks(wcn);
429 out_smd_close:
430 wcn36xx_smd_close(wcn);
431 out_err:
432 return ret;
433 }
434
435 static void wcn36xx_stop(struct ieee80211_hw *hw)
436 {
437 struct wcn36xx *wcn = hw->priv;
438
439 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n");
440
441 wcn36xx_debugfs_exit(wcn);
442 wcn36xx_smd_stop(wcn);
443 wcn36xx_dxe_deinit(wcn);
444 wcn36xx_smd_close(wcn);
445
446 wcn36xx_dxe_free_mem_pools(wcn);
447 wcn36xx_dxe_free_ctl_blks(wcn);
448
449 kfree(wcn->hal_buf);
450 }
451
452 static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
453 {
454 struct wcn36xx *wcn = hw->priv;
455 struct ieee80211_vif *vif = NULL;
456 struct wcn36xx_vif *tmp;
457
458 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
459
460 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
461 int ch = WCN36XX_HW_CHANNEL(wcn);
462 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
463 ch);
464 list_for_each_entry(tmp, &wcn->vif_list, list) {
465 vif = container_of((void *)tmp,
466 struct ieee80211_vif,
467 drv_priv);
468 wcn36xx_smd_switch_channel(wcn, vif, ch);
469 }
470 }
471
472 return 0;
473 }
474
475 #define WCN36XX_SUPPORTED_FILTERS (0)
476
477 static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
478 unsigned int changed,
479 unsigned int *total, u64 multicast)
480 {
481 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
482
483 *total &= WCN36XX_SUPPORTED_FILTERS;
484 }
485
486 static void wcn36xx_tx(struct ieee80211_hw *hw,
487 struct ieee80211_tx_control *control,
488 struct sk_buff *skb)
489 {
490 struct wcn36xx *wcn = hw->priv;
491 struct wcn36xx_sta *sta_priv = NULL;
492
493 if (control->sta)
494 sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv;
495
496 if (wcn36xx_start_tx(wcn, sta_priv, skb))
497 ieee80211_free_txskb(wcn->hw, skb);
498 }
499
500 static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
501 struct ieee80211_vif *vif,
502 struct ieee80211_sta *sta,
503 struct ieee80211_key_conf *key_conf)
504 {
505 struct wcn36xx *wcn = hw->priv;
506 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
507 struct wcn36xx_sta *sta_priv = vif_priv->sta;
508 int ret = 0;
509 u8 key[WLAN_MAX_KEY_LEN];
510
511 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n");
512 wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n",
513 cmd, key_conf->cipher, key_conf->keyidx,
514 key_conf->keylen, key_conf->flags);
515 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ",
516 key_conf->key,
517 key_conf->keylen);
518
519 switch (key_conf->cipher) {
520 case WLAN_CIPHER_SUITE_WEP40:
521 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
522 break;
523 case WLAN_CIPHER_SUITE_WEP104:
524 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
525 break;
526 case WLAN_CIPHER_SUITE_CCMP:
527 vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
528 break;
529 case WLAN_CIPHER_SUITE_TKIP:
530 vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP;
531 break;
532 default:
533 wcn36xx_err("Unsupported key type 0x%x\n",
534 key_conf->cipher);
535 ret = -EOPNOTSUPP;
536 goto out;
537 }
538
539 switch (cmd) {
540 case SET_KEY:
541 if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) {
542 /*
543 * Supplicant is sending key in the wrong order:
544 * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b)
545 * but HW expects it to be in the order as described in
546 * IEEE 802.11 spec (see chapter 11.7) like this:
547 * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b)
548 */
549 memcpy(key, key_conf->key, 16);
550 memcpy(key + 16, key_conf->key + 24, 8);
551 memcpy(key + 24, key_conf->key + 16, 8);
552 } else {
553 memcpy(key, key_conf->key, key_conf->keylen);
554 }
555
556 if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
557 sta_priv->is_data_encrypted = true;
558 /* Reconfigure bss with encrypt_type */
559 if (NL80211_IFTYPE_STATION == vif->type)
560 wcn36xx_smd_config_bss(wcn,
561 vif,
562 sta,
563 sta->addr,
564 true);
565
566 wcn36xx_smd_set_stakey(wcn,
567 vif_priv->encrypt_type,
568 key_conf->keyidx,
569 key_conf->keylen,
570 key,
571 get_sta_index(vif, sta_priv));
572 } else {
573 wcn36xx_smd_set_bsskey(wcn,
574 vif_priv->encrypt_type,
575 key_conf->keyidx,
576 key_conf->keylen,
577 key);
578 if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
579 (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
580 sta_priv->is_data_encrypted = true;
581 wcn36xx_smd_set_stakey(wcn,
582 vif_priv->encrypt_type,
583 key_conf->keyidx,
584 key_conf->keylen,
585 key,
586 get_sta_index(vif, sta_priv));
587 }
588 }
589 break;
590 case DISABLE_KEY:
591 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
592 wcn36xx_smd_remove_bsskey(wcn,
593 vif_priv->encrypt_type,
594 key_conf->keyidx);
595 } else {
596 sta_priv->is_data_encrypted = false;
597 /* do not remove key if disassociated */
598 if (sta_priv->aid)
599 wcn36xx_smd_remove_stakey(wcn,
600 vif_priv->encrypt_type,
601 key_conf->keyidx,
602 get_sta_index(vif, sta_priv));
603 }
604 break;
605 default:
606 wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
607 ret = -EOPNOTSUPP;
608 goto out;
609 }
610
611 out:
612 return ret;
613 }
614
615 static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
616 struct ieee80211_vif *vif,
617 const u8 *mac_addr)
618 {
619 struct wcn36xx *wcn = hw->priv;
620
621 wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
622 wcn36xx_smd_start_scan(wcn);
623 }
624
625 static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
626 struct ieee80211_vif *vif)
627 {
628 struct wcn36xx *wcn = hw->priv;
629
630 wcn36xx_smd_end_scan(wcn);
631 wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
632 }
633
634 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
635 enum ieee80211_band band)
636 {
637 int i, size;
638 u16 *rates_table;
639 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
640 u32 rates = sta->supp_rates[band];
641
642 memset(&sta_priv->supported_rates, 0,
643 sizeof(sta_priv->supported_rates));
644 sta_priv->supported_rates.op_rate_mode = STA_11n;
645
646 size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates);
647 rates_table = sta_priv->supported_rates.dsss_rates;
648 if (band == IEEE80211_BAND_2GHZ) {
649 for (i = 0; i < size; i++) {
650 if (rates & 0x01) {
651 rates_table[i] = wcn_2ghz_rates[i].hw_value;
652 rates = rates >> 1;
653 }
654 }
655 }
656
657 size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates);
658 rates_table = sta_priv->supported_rates.ofdm_rates;
659 for (i = 0; i < size; i++) {
660 if (rates & 0x01) {
661 rates_table[i] = wcn_5ghz_rates[i].hw_value;
662 rates = rates >> 1;
663 }
664 }
665
666 if (sta->ht_cap.ht_supported) {
667 BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) >
668 sizeof(sta_priv->supported_rates.supported_mcs_set));
669 memcpy(sta_priv->supported_rates.supported_mcs_set,
670 sta->ht_cap.mcs.rx_mask,
671 sizeof(sta->ht_cap.mcs.rx_mask));
672 }
673 }
674 void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
675 {
676 u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = {
677 HW_RATE_INDEX_6MBPS,
678 HW_RATE_INDEX_9MBPS,
679 HW_RATE_INDEX_12MBPS,
680 HW_RATE_INDEX_18MBPS,
681 HW_RATE_INDEX_24MBPS,
682 HW_RATE_INDEX_36MBPS,
683 HW_RATE_INDEX_48MBPS,
684 HW_RATE_INDEX_54MBPS
685 };
686 u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = {
687 HW_RATE_INDEX_1MBPS,
688 HW_RATE_INDEX_2MBPS,
689 HW_RATE_INDEX_5_5MBPS,
690 HW_RATE_INDEX_11MBPS
691 };
692
693 rates->op_rate_mode = STA_11n;
694 memcpy(rates->dsss_rates, dsss_rates,
695 sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES);
696 memcpy(rates->ofdm_rates, ofdm_rates,
697 sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES);
698 rates->supported_mcs_set[0] = 0xFF;
699 }
700 static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
701 struct ieee80211_vif *vif,
702 struct ieee80211_bss_conf *bss_conf,
703 u32 changed)
704 {
705 struct wcn36xx *wcn = hw->priv;
706 struct sk_buff *skb = NULL;
707 u16 tim_off, tim_len;
708 enum wcn36xx_hal_link_state link_state;
709 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
710
711 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
712 vif, changed);
713
714 if (changed & BSS_CHANGED_BEACON_INFO) {
715 wcn36xx_dbg(WCN36XX_DBG_MAC,
716 "mac bss changed dtim period %d\n",
717 bss_conf->dtim_period);
718
719 vif_priv->dtim_period = bss_conf->dtim_period;
720 }
721
722 if (changed & BSS_CHANGED_PS) {
723 wcn36xx_dbg(WCN36XX_DBG_MAC,
724 "mac bss PS set %d\n",
725 bss_conf->ps);
726 if (bss_conf->ps) {
727 wcn36xx_pmc_enter_bmps_state(wcn, vif);
728 } else {
729 wcn36xx_pmc_exit_bmps_state(wcn, vif);
730 }
731 }
732
733 if (changed & BSS_CHANGED_BSSID) {
734 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
735 bss_conf->bssid);
736
737 if (!is_zero_ether_addr(bss_conf->bssid)) {
738 vif_priv->is_joining = true;
739 vif_priv->bss_index = 0xff;
740 wcn36xx_smd_join(wcn, bss_conf->bssid,
741 vif->addr, WCN36XX_HW_CHANNEL(wcn));
742 wcn36xx_smd_config_bss(wcn, vif, NULL,
743 bss_conf->bssid, false);
744 } else {
745 vif_priv->is_joining = false;
746 wcn36xx_smd_delete_bss(wcn, vif);
747 }
748 }
749
750 if (changed & BSS_CHANGED_SSID) {
751 wcn36xx_dbg(WCN36XX_DBG_MAC,
752 "mac bss changed ssid\n");
753 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ",
754 bss_conf->ssid, bss_conf->ssid_len);
755
756 vif_priv->ssid.length = bss_conf->ssid_len;
757 memcpy(&vif_priv->ssid.ssid,
758 bss_conf->ssid,
759 bss_conf->ssid_len);
760 }
761
762 if (changed & BSS_CHANGED_ASSOC) {
763 vif_priv->is_joining = false;
764 if (bss_conf->assoc) {
765 struct ieee80211_sta *sta;
766 struct wcn36xx_sta *sta_priv;
767
768 wcn36xx_dbg(WCN36XX_DBG_MAC,
769 "mac assoc bss %pM vif %pM AID=%d\n",
770 bss_conf->bssid,
771 vif->addr,
772 bss_conf->aid);
773
774 rcu_read_lock();
775 sta = ieee80211_find_sta(vif, bss_conf->bssid);
776 if (!sta) {
777 wcn36xx_err("sta %pM is not found\n",
778 bss_conf->bssid);
779 rcu_read_unlock();
780 goto out;
781 }
782 sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
783
784 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
785
786 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid,
787 vif->addr,
788 WCN36XX_HAL_LINK_POSTASSOC_STATE);
789 wcn36xx_smd_config_bss(wcn, vif, sta,
790 bss_conf->bssid,
791 true);
792 sta_priv->aid = bss_conf->aid;
793 /*
794 * config_sta must be called from because this is the
795 * place where AID is available.
796 */
797 wcn36xx_smd_config_sta(wcn, vif, sta);
798 rcu_read_unlock();
799 } else {
800 wcn36xx_dbg(WCN36XX_DBG_MAC,
801 "disassociated bss %pM vif %pM AID=%d\n",
802 bss_conf->bssid,
803 vif->addr,
804 bss_conf->aid);
805 wcn36xx_smd_set_link_st(wcn,
806 bss_conf->bssid,
807 vif->addr,
808 WCN36XX_HAL_LINK_IDLE_STATE);
809 }
810 }
811
812 if (changed & BSS_CHANGED_AP_PROBE_RESP) {
813 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n");
814 skb = ieee80211_proberesp_get(hw, vif);
815 if (!skb) {
816 wcn36xx_err("failed to alloc probereq skb\n");
817 goto out;
818 }
819
820 wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb);
821 dev_kfree_skb(skb);
822 }
823
824 if (changed & BSS_CHANGED_BEACON_ENABLED ||
825 changed & BSS_CHANGED_BEACON) {
826 wcn36xx_dbg(WCN36XX_DBG_MAC,
827 "mac bss changed beacon enabled %d\n",
828 bss_conf->enable_beacon);
829
830 if (bss_conf->enable_beacon) {
831 vif_priv->dtim_period = bss_conf->dtim_period;
832 vif_priv->bss_index = 0xff;
833 wcn36xx_smd_config_bss(wcn, vif, NULL,
834 vif->addr, false);
835 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
836 &tim_len);
837 if (!skb) {
838 wcn36xx_err("failed to alloc beacon skb\n");
839 goto out;
840 }
841 wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0);
842 dev_kfree_skb(skb);
843
844 if (vif->type == NL80211_IFTYPE_ADHOC ||
845 vif->type == NL80211_IFTYPE_MESH_POINT)
846 link_state = WCN36XX_HAL_LINK_IBSS_STATE;
847 else
848 link_state = WCN36XX_HAL_LINK_AP_STATE;
849
850 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
851 link_state);
852 } else {
853 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
854 WCN36XX_HAL_LINK_IDLE_STATE);
855 wcn36xx_smd_delete_bss(wcn, vif);
856 }
857 }
858 out:
859 return;
860 }
861
862 /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */
863 static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
864 {
865 struct wcn36xx *wcn = hw->priv;
866 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
867
868 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
869 return 0;
870 }
871
872 static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
873 struct ieee80211_vif *vif)
874 {
875 struct wcn36xx *wcn = hw->priv;
876 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
877 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
878
879 list_del(&vif_priv->list);
880 wcn36xx_smd_delete_sta_self(wcn, vif->addr);
881 }
882
883 static int wcn36xx_add_interface(struct ieee80211_hw *hw,
884 struct ieee80211_vif *vif)
885 {
886 struct wcn36xx *wcn = hw->priv;
887 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
888
889 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
890 vif, vif->type);
891
892 if (!(NL80211_IFTYPE_STATION == vif->type ||
893 NL80211_IFTYPE_AP == vif->type ||
894 NL80211_IFTYPE_ADHOC == vif->type ||
895 NL80211_IFTYPE_MESH_POINT == vif->type)) {
896 wcn36xx_warn("Unsupported interface type requested: %d\n",
897 vif->type);
898 return -EOPNOTSUPP;
899 }
900
901 list_add(&vif_priv->list, &wcn->vif_list);
902 wcn36xx_smd_add_sta_self(wcn, vif);
903
904 return 0;
905 }
906
907 static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
908 struct ieee80211_sta *sta)
909 {
910 struct wcn36xx *wcn = hw->priv;
911 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
912 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
913 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
914 vif, sta->addr);
915
916 spin_lock_init(&sta_priv->ampdu_lock);
917 vif_priv->sta = sta_priv;
918 sta_priv->vif = vif_priv;
919 /*
920 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
921 * at this stage AID is not available yet.
922 */
923 if (NL80211_IFTYPE_STATION != vif->type) {
924 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
925 sta_priv->aid = sta->aid;
926 wcn36xx_smd_config_sta(wcn, vif, sta);
927 }
928 return 0;
929 }
930
931 static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
932 struct ieee80211_vif *vif,
933 struct ieee80211_sta *sta)
934 {
935 struct wcn36xx *wcn = hw->priv;
936 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
937 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
938
939 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
940 vif, sta->addr, sta_priv->sta_index);
941
942 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
943 vif_priv->sta = NULL;
944 sta_priv->vif = NULL;
945 return 0;
946 }
947
948 #ifdef CONFIG_PM
949
950 static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
951 {
952 struct wcn36xx *wcn = hw->priv;
953
954 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n");
955
956 flush_workqueue(wcn->hal_ind_wq);
957 wcn36xx_smd_set_power_params(wcn, true);
958 return 0;
959 }
960
961 static int wcn36xx_resume(struct ieee80211_hw *hw)
962 {
963 struct wcn36xx *wcn = hw->priv;
964
965 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n");
966
967 flush_workqueue(wcn->hal_ind_wq);
968 wcn36xx_smd_set_power_params(wcn, false);
969 return 0;
970 }
971
972 #endif
973
974 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
975 struct ieee80211_vif *vif,
976 enum ieee80211_ampdu_mlme_action action,
977 struct ieee80211_sta *sta, u16 tid, u16 *ssn,
978 u8 buf_size, bool amsdu)
979 {
980 struct wcn36xx *wcn = hw->priv;
981 struct wcn36xx_sta *sta_priv = NULL;
982
983 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
984 action, tid);
985
986 sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
987
988 switch (action) {
989 case IEEE80211_AMPDU_RX_START:
990 sta_priv->tid = tid;
991 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
992 get_sta_index(vif, sta_priv));
993 wcn36xx_smd_add_ba(wcn);
994 wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv));
995 break;
996 case IEEE80211_AMPDU_RX_STOP:
997 wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv));
998 break;
999 case IEEE80211_AMPDU_TX_START:
1000 spin_lock_bh(&sta_priv->ampdu_lock);
1001 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
1002 spin_unlock_bh(&sta_priv->ampdu_lock);
1003
1004 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1005 break;
1006 case IEEE80211_AMPDU_TX_OPERATIONAL:
1007 spin_lock_bh(&sta_priv->ampdu_lock);
1008 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
1009 spin_unlock_bh(&sta_priv->ampdu_lock);
1010
1011 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
1012 get_sta_index(vif, sta_priv));
1013 break;
1014 case IEEE80211_AMPDU_TX_STOP_FLUSH:
1015 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1016 case IEEE80211_AMPDU_TX_STOP_CONT:
1017 spin_lock_bh(&sta_priv->ampdu_lock);
1018 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE;
1019 spin_unlock_bh(&sta_priv->ampdu_lock);
1020
1021 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1022 break;
1023 default:
1024 wcn36xx_err("Unknown AMPDU action\n");
1025 }
1026
1027 return 0;
1028 }
1029
1030 static const struct ieee80211_ops wcn36xx_ops = {
1031 .start = wcn36xx_start,
1032 .stop = wcn36xx_stop,
1033 .add_interface = wcn36xx_add_interface,
1034 .remove_interface = wcn36xx_remove_interface,
1035 #ifdef CONFIG_PM
1036 .suspend = wcn36xx_suspend,
1037 .resume = wcn36xx_resume,
1038 #endif
1039 .config = wcn36xx_config,
1040 .configure_filter = wcn36xx_configure_filter,
1041 .tx = wcn36xx_tx,
1042 .set_key = wcn36xx_set_key,
1043 .sw_scan_start = wcn36xx_sw_scan_start,
1044 .sw_scan_complete = wcn36xx_sw_scan_complete,
1045 .bss_info_changed = wcn36xx_bss_info_changed,
1046 .set_rts_threshold = wcn36xx_set_rts_threshold,
1047 .sta_add = wcn36xx_sta_add,
1048 .sta_remove = wcn36xx_sta_remove,
1049 .ampdu_action = wcn36xx_ampdu_action,
1050 };
1051
1052 static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
1053 {
1054 int ret = 0;
1055
1056 static const u32 cipher_suites[] = {
1057 WLAN_CIPHER_SUITE_WEP40,
1058 WLAN_CIPHER_SUITE_WEP104,
1059 WLAN_CIPHER_SUITE_TKIP,
1060 WLAN_CIPHER_SUITE_CCMP,
1061 };
1062
1063 ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY);
1064 ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION);
1065 ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR);
1066 ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
1067 ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
1068 ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
1069
1070 wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1071 BIT(NL80211_IFTYPE_AP) |
1072 BIT(NL80211_IFTYPE_ADHOC) |
1073 BIT(NL80211_IFTYPE_MESH_POINT);
1074
1075 wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz;
1076 wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz;
1077
1078 wcn->hw->wiphy->cipher_suites = cipher_suites;
1079 wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
1080
1081 wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
1082
1083 #ifdef CONFIG_PM
1084 wcn->hw->wiphy->wowlan = &wowlan_support;
1085 #endif
1086
1087 wcn->hw->max_listen_interval = 200;
1088
1089 wcn->hw->queues = 4;
1090
1091 SET_IEEE80211_DEV(wcn->hw, wcn->dev);
1092
1093 wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta);
1094 wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif);
1095
1096 return ret;
1097 }
1098
1099 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
1100 struct platform_device *pdev)
1101 {
1102 struct resource *res;
1103 /* Set TX IRQ */
1104 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1105 "wcnss_wlantx_irq");
1106 if (!res) {
1107 wcn36xx_err("failed to get tx_irq\n");
1108 return -ENOENT;
1109 }
1110 wcn->tx_irq = res->start;
1111
1112 /* Set RX IRQ */
1113 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1114 "wcnss_wlanrx_irq");
1115 if (!res) {
1116 wcn36xx_err("failed to get rx_irq\n");
1117 return -ENOENT;
1118 }
1119 wcn->rx_irq = res->start;
1120
1121 /* Map the memory */
1122 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1123 "wcnss_mmio");
1124 if (!res) {
1125 wcn36xx_err("failed to get mmio\n");
1126 return -ENOENT;
1127 }
1128 wcn->mmio = ioremap(res->start, resource_size(res));
1129 if (!wcn->mmio) {
1130 wcn36xx_err("failed to map io memory\n");
1131 return -ENOMEM;
1132 }
1133 return 0;
1134 }
1135
1136 static int wcn36xx_probe(struct platform_device *pdev)
1137 {
1138 struct ieee80211_hw *hw;
1139 struct wcn36xx *wcn;
1140 int ret;
1141 u8 addr[ETH_ALEN];
1142
1143 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
1144
1145 hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
1146 if (!hw) {
1147 wcn36xx_err("failed to alloc hw\n");
1148 ret = -ENOMEM;
1149 goto out_err;
1150 }
1151 platform_set_drvdata(pdev, hw);
1152 wcn = hw->priv;
1153 wcn->hw = hw;
1154 wcn->dev = &pdev->dev;
1155 wcn->ctrl_ops = pdev->dev.platform_data;
1156
1157 mutex_init(&wcn->hal_mutex);
1158
1159 if (!wcn->ctrl_ops->get_hw_mac(addr)) {
1160 wcn36xx_info("mac address: %pM\n", addr);
1161 SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
1162 }
1163
1164 ret = wcn36xx_platform_get_resources(wcn, pdev);
1165 if (ret)
1166 goto out_wq;
1167
1168 wcn36xx_init_ieee80211(wcn);
1169 ret = ieee80211_register_hw(wcn->hw);
1170 if (ret)
1171 goto out_unmap;
1172
1173 return 0;
1174
1175 out_unmap:
1176 iounmap(wcn->mmio);
1177 out_wq:
1178 ieee80211_free_hw(hw);
1179 out_err:
1180 return ret;
1181 }
1182 static int wcn36xx_remove(struct platform_device *pdev)
1183 {
1184 struct ieee80211_hw *hw = platform_get_drvdata(pdev);
1185 struct wcn36xx *wcn = hw->priv;
1186 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
1187
1188 release_firmware(wcn->nv);
1189 mutex_destroy(&wcn->hal_mutex);
1190
1191 ieee80211_unregister_hw(hw);
1192 iounmap(wcn->mmio);
1193 ieee80211_free_hw(hw);
1194
1195 return 0;
1196 }
1197 static const struct platform_device_id wcn36xx_platform_id_table[] = {
1198 {
1199 .name = "wcn36xx",
1200 .driver_data = 0
1201 },
1202 {}
1203 };
1204 MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
1205
1206 static struct platform_driver wcn36xx_driver = {
1207 .probe = wcn36xx_probe,
1208 .remove = wcn36xx_remove,
1209 .driver = {
1210 .name = "wcn36xx",
1211 },
1212 .id_table = wcn36xx_platform_id_table,
1213 };
1214
1215 static int __init wcn36xx_init(void)
1216 {
1217 platform_driver_register(&wcn36xx_driver);
1218 return 0;
1219 }
1220 module_init(wcn36xx_init);
1221
1222 static void __exit wcn36xx_exit(void)
1223 {
1224 platform_driver_unregister(&wcn36xx_driver);
1225 }
1226 module_exit(wcn36xx_exit);
1227
1228 MODULE_LICENSE("Dual BSD/GPL");
1229 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
1230 MODULE_FIRMWARE(WLAN_NV_FILE);
1231
1232 #line 116 "/work/ldvuser/andrianov/work/current--X--drivers/net/wireless/ath/wcn36xx/--X--defaultlinux-4.5-rc7--X--races--X--cpachecker/linux-4.5-rc7/csd_deg_dscv/19/dscv_tempdir/dscv/ri/races/drivers/net/wireless/ath/wcn36xx/main.o.c.prepared"
1233
1234 int ldv_retval_5;
1235 int ldv_retval_0;
1236 int ldv_retval_4;
1237 void ldv_initialize(void);
1238 void ldv_check_final_state(void);
1239 int ldv_retval_2;
1240
1241
1242 void ldv_initialyze_ieee80211_ops_6(void){
1243 wcn36xx_ops_group0 = ldv_undef_ptr();
1244 }
1245
1246 int evil_hack_key_6(void){
1247 mutex_lock(&key_mtx);
1248 return 1;
1249 }
1250
1251
1252 int evil_hack_6(void){
1253 rtnl_lock();
1254 return 1;
1255 }
1256
1257
1258 void ldv_platform_probe_5(int (*probe)(struct platform_device *)){
1259 int err;
1260 err = probe(wcn36xx_driver_group1);
1261 if(err == 0){
1262 probed_5 = 1;
1263 ref_cnt++;
1264 }
1265 }
1266
1267
1268 int evil_hack_fs_lock(void){
1269 mutex_lock(&fs_mutex);
1270 return 1;
1271 }
1272
1273 int __VERIFIER_nondet_int(void);
1274
1275 void ldv_platform_driver_init_5(void){
1276 wcn36xx_driver_group1 = ldv_undef_ptr();
1277 }
1278
1279
1280 int evil_hack_ar_lock(void){
1281 mutex_lock(&ar_mutex);
1282 return 1;
1283 }
1284
1285
1286 /* DEG-ENVIRONMENT-BEGIN */
1287 extern void ldv_main_exported_4(void);
1288 extern void ldv_main_exported_3(void);
1289 extern void ldv_main_exported_6(void);
1290 extern void ldv_main_exported_0(void);
1291 extern void ldv_main_exported_5(void);
1292
1293 //********************* LDV MAIN *********************
1294 //main
1295 void entry_point(void){
1296 ldv_initialize();
1297 //args for callbacks
1298 struct ieee80211_tx_control *ldvarg18;
1299 enum ieee80211_ampdu_mlme_action ldvarg11;
1300 struct ieee80211_vif *ldvarg20;
1301 u64 ldvarg7;
1302 struct ieee80211_bss_conf *ldvarg23;
1303 struct ieee80211_vif *ldvarg3;
1304 u8 ldvarg12;
1305 unsigned int *ldvarg8;
1306 struct ieee80211_sta *ldvarg1;
1307 struct ieee80211_vif *ldvarg13;
1308 struct ieee80211_key_conf *ldvarg29;
1309 u16 *ldvarg10;
1310 unsigned int ldvarg9;
1311 struct ieee80211_vif *ldvarg24;
1312 enum set_key_cmd ldvarg27;
1313 struct ieee80211_vif *ldvarg26;
1314 struct ieee80211_vif *ldvarg0;
1315 u8 const *ldvarg5;
1316 u32 ldvarg30;
1317 u16 ldvarg16;
1318 struct ieee80211_vif *ldvarg6;
1319 struct ieee80211_sta *ldvarg15;
1320 struct ieee80211_vif *ldvarg21;
1321 u32 ldvarg25;
1322 struct sk_buff *ldvarg17;
1323 u32 ldvarg4;
1324 bool ldvarg14;
1325 struct cfg80211_wowlan *ldvarg22;
1326 struct ieee80211_sta *ldvarg19;
1327 struct ieee80211_sta *ldvarg28;
1328 struct ieee80211_vif *ldvarg2;
1329 //initialization of machine states
1330 ldv_state_variable_6=0;
1331 ldv_state_variable_4=0;
1332
1333 ldv_state_variable_1=1;
1334 ref_cnt=0;
1335 ldv_state_variable_0=1;
1336 ldv_state_variable_3=0;
1337
1338 ldv_state_variable_2=1;
1339 ldv_state_variable_5=0;
1340 while(1){
1341 switch(__VERIFIER_nondet_int()){
1342 case 0:{
1343 /*DEG-struct: handlers from structure wcn36xx_ops*/
1344 /*DEG-CHECK: checking registration of wcn36xx_ops structure*/
1345 if(ldv_state_variable_6 != 0){
1346 switch(__VERIFIER_nondet_int()){
1347 case 0:{
1348 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1349 if(ldv_state_variable_6 == 1 && evil_hack_6()){
1350 /*DEG-CALL: handler start from wcn36xx_ops*/
1351 ldv_retval_0=(& wcn36xx_start)(wcn36xx_ops_group0);
1352 /*DEG-postcall: Invoke callback with role ieee80211_ops.start*/
1353 if(ldv_retval_0==0){
1354 ldv_state_variable_6 = 2;
1355 ref_cnt++;
1356 }
1357 }
1358 }
1359 break;
1360 case 1:{
1361 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1362 if(ldv_state_variable_6 == 1){
1363 /*DEG-CALL: handler config from wcn36xx_ops*/
1364 (& wcn36xx_config)(wcn36xx_ops_group0,ldvarg30);
1365 /*DEG-postcall: default*/
1366 ldv_state_variable_6 = 1;
1367 }
1368 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1369 if(ldv_state_variable_6 == 2){
1370 /*DEG-CALL: handler config from wcn36xx_ops*/
1371 (& wcn36xx_config)(wcn36xx_ops_group0,ldvarg30);
1372 /*DEG-postcall: default*/
1373 ldv_state_variable_6 = 2;
1374 }
1375 }
1376 break;
1377 case 2:{
1378 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1379 if(ldv_state_variable_6 == 2 && evil_hack_key_6()){
1380 /*DEG-CALL: handler set_key from wcn36xx_ops*/
1381 (& wcn36xx_set_key)(wcn36xx_ops_group0,ldvarg27,ldvarg26,ldvarg28,ldvarg29);
1382 ldv_state_variable_6 = 2;
1383 mutex_unlock(&key_mtx);
1384 }
1385 }
1386 break;
1387 case 3:{
1388 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1389 if(ldv_state_variable_6 == 1){
1390 /*DEG-CALL: handler bss_info_changed from wcn36xx_ops*/
1391 (& wcn36xx_bss_info_changed)(wcn36xx_ops_group0,ldvarg24,ldvarg23,ldvarg25);
1392 /*DEG-postcall: default*/
1393 ldv_state_variable_6 = 1;
1394 }
1395 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1396 if(ldv_state_variable_6 == 2){
1397 /*DEG-CALL: handler bss_info_changed from wcn36xx_ops*/
1398 (& wcn36xx_bss_info_changed)(wcn36xx_ops_group0,ldvarg24,ldvarg23,ldvarg25);
1399 /*DEG-postcall: default*/
1400 ldv_state_variable_6 = 2;
1401 }
1402 }
1403 break;
1404 case 4:{
1405 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1406 if(ldv_state_variable_6 == 1){
1407 /*DEG-CALL: handler suspend from wcn36xx_ops*/
1408 (& wcn36xx_suspend)(wcn36xx_ops_group0,ldvarg22);
1409 /*DEG-postcall: default*/
1410 ldv_state_variable_6 = 1;
1411 }
1412 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1413 if(ldv_state_variable_6 == 2){
1414 /*DEG-CALL: handler suspend from wcn36xx_ops*/
1415 (& wcn36xx_suspend)(wcn36xx_ops_group0,ldvarg22);
1416 /*DEG-postcall: default*/
1417 ldv_state_variable_6 = 2;
1418 }
1419 }
1420 break;
1421 case 5:{
1422 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1423 if(ldv_state_variable_6 == 1){
1424 /*DEG-CALL: handler sw_scan_complete from wcn36xx_ops*/
1425 (& wcn36xx_sw_scan_complete)(wcn36xx_ops_group0,ldvarg21);
1426 /*DEG-postcall: default*/
1427 ldv_state_variable_6 = 1;
1428 }
1429 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1430 if(ldv_state_variable_6 == 2){
1431 /*DEG-CALL: handler sw_scan_complete from wcn36xx_ops*/
1432 (& wcn36xx_sw_scan_complete)(wcn36xx_ops_group0,ldvarg21);
1433 /*DEG-postcall: default*/
1434 ldv_state_variable_6 = 2;
1435 }
1436 }
1437 break;
1438 case 6:{
1439 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1440 if(ldv_state_variable_6 == 1){
1441 /*DEG-CALL: handler sta_add from wcn36xx_ops*/
1442 (& wcn36xx_sta_add)(wcn36xx_ops_group0,ldvarg20,ldvarg19);
1443 /*DEG-postcall: default*/
1444 ldv_state_variable_6 = 1;
1445 }
1446 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1447 if(ldv_state_variable_6 == 2){
1448 /*DEG-CALL: handler sta_add from wcn36xx_ops*/
1449 (& wcn36xx_sta_add)(wcn36xx_ops_group0,ldvarg20,ldvarg19);
1450 /*DEG-postcall: default*/
1451 ldv_state_variable_6 = 2;
1452 }
1453 }
1454 break;
1455 case 7:{
1456 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1457 if(ldv_state_variable_6 == 2 && evil_hack_6()){
1458 /*DEG-CALL: handler stop from wcn36xx_ops*/
1459 (& wcn36xx_stop)(wcn36xx_ops_group0);
1460 /*DEG-postcall: Invoke callback with role ieee80211_ops.stop*/
1461 ldv_state_variable_6 = 1;
1462 ref_cnt--;
1463 rtnl_unlock();
1464 }
1465 }
1466 break;
1467 case 8:{
1468 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1469 if(ldv_state_variable_6 == 1){
1470 /*DEG-CALL: handler tx from wcn36xx_ops*/
1471 (& wcn36xx_tx)(wcn36xx_ops_group0,ldvarg18,ldvarg17);
1472 /*DEG-postcall: default*/
1473 ldv_state_variable_6 = 1;
1474 }
1475 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1476 if(ldv_state_variable_6 == 2){
1477 /*DEG-CALL: handler tx from wcn36xx_ops*/
1478 (& wcn36xx_tx)(wcn36xx_ops_group0,ldvarg18,ldvarg17);
1479 /*DEG-postcall: default*/
1480 ldv_state_variable_6 = 2;
1481 }
1482 }
1483 break;
1484 case 9:{
1485 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1486 if(ldv_state_variable_6 == 1){
1487 /*DEG-CALL: handler resume from wcn36xx_ops*/
1488 (& wcn36xx_resume)(wcn36xx_ops_group0);
1489 /*DEG-postcall: default*/
1490 ldv_state_variable_6 = 1;
1491 }
1492 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1493 if(ldv_state_variable_6 == 2){
1494 /*DEG-CALL: handler resume from wcn36xx_ops*/
1495 (& wcn36xx_resume)(wcn36xx_ops_group0);
1496 /*DEG-postcall: default*/
1497 ldv_state_variable_6 = 2;
1498 }
1499 }
1500 break;
1501 case 10:{
1502 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1503 if(ldv_state_variable_6 == 1){
1504 /*DEG-CALL: handler ampdu_action from wcn36xx_ops*/
1505 (& wcn36xx_ampdu_action)(wcn36xx_ops_group0,ldvarg13,ldvarg11,ldvarg15,ldvarg16,ldvarg10,ldvarg12,ldvarg14);
1506 /*DEG-postcall: default*/
1507 ldv_state_variable_6 = 1;
1508 }
1509 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1510 if(ldv_state_variable_6 == 2){
1511 /*DEG-CALL: handler ampdu_action from wcn36xx_ops*/
1512 (& wcn36xx_ampdu_action)(wcn36xx_ops_group0,ldvarg13,ldvarg11,ldvarg15,ldvarg16,ldvarg10,ldvarg12,ldvarg14);
1513 /*DEG-postcall: default*/
1514 ldv_state_variable_6 = 2;
1515 }
1516 }
1517 break;
1518 case 11:{
1519 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1520 if(ldv_state_variable_6 == 2 && evil_hack_6()){
1521 /*DEG-CALL: handler configure_filter from wcn36xx_ops*/
1522 (& wcn36xx_configure_filter)(wcn36xx_ops_group0,ldvarg9,ldvarg8,ldvarg7);
1523 ldv_state_variable_6 = 2;
1524 rtnl_unlock();
1525 }
1526 }
1527 break;
1528 case 12:{
1529 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1530 if(ldv_state_variable_6 == 1){
1531 /*DEG-CALL: handler sw_scan_start from wcn36xx_ops*/
1532 (& wcn36xx_sw_scan_start)(wcn36xx_ops_group0,ldvarg6,ldvarg5);
1533 /*DEG-postcall: default*/
1534 ldv_state_variable_6 = 1;
1535 }
1536 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1537 if(ldv_state_variable_6 == 2){
1538 /*DEG-CALL: handler sw_scan_start from wcn36xx_ops*/
1539 (& wcn36xx_sw_scan_start)(wcn36xx_ops_group0,ldvarg6,ldvarg5);
1540 /*DEG-postcall: default*/
1541 ldv_state_variable_6 = 2;
1542 }
1543 }
1544 break;
1545 case 13:{
1546 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1547 if(ldv_state_variable_6 == 1){
1548 /*DEG-CALL: handler set_rts_threshold from wcn36xx_ops*/
1549 (& wcn36xx_set_rts_threshold)(wcn36xx_ops_group0,ldvarg4);
1550 /*DEG-postcall: default*/
1551 ldv_state_variable_6 = 1;
1552 }
1553 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1554 if(ldv_state_variable_6 == 2){
1555 /*DEG-CALL: handler set_rts_threshold from wcn36xx_ops*/
1556 (& wcn36xx_set_rts_threshold)(wcn36xx_ops_group0,ldvarg4);
1557 /*DEG-postcall: default*/
1558 ldv_state_variable_6 = 2;
1559 }
1560 }
1561 break;
1562 case 14:{
1563 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1564 if(ldv_state_variable_6 == 2 && evil_hack_6()){
1565 /*DEG-CALL: handler add_interface from wcn36xx_ops*/
1566 (& wcn36xx_add_interface)(wcn36xx_ops_group0,ldvarg3);
1567 ldv_state_variable_6 = 2;
1568 rtnl_unlock();
1569 }
1570 }
1571 break;
1572 case 15:{
1573 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1574 if(ldv_state_variable_6 == 1){
1575 /*DEG-CALL: handler sta_remove from wcn36xx_ops*/
1576 (& wcn36xx_sta_remove)(wcn36xx_ops_group0,ldvarg2,ldvarg1);
1577 /*DEG-postcall: default*/
1578 ldv_state_variable_6 = 1;
1579 }
1580 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1581 if(ldv_state_variable_6 == 2){
1582 /*DEG-CALL: handler sta_remove from wcn36xx_ops*/
1583 (& wcn36xx_sta_remove)(wcn36xx_ops_group0,ldvarg2,ldvarg1);
1584 /*DEG-postcall: default*/
1585 ldv_state_variable_6 = 2;
1586 }
1587 }
1588 break;
1589 case 16:{
1590 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1591 if(ldv_state_variable_6 == 2 && evil_hack_6()){
1592 /*DEG-CALL: handler remove_interface from wcn36xx_ops*/
1593 (& wcn36xx_remove_interface)(wcn36xx_ops_group0,ldvarg0);
1594 ldv_state_variable_6 = 2;
1595 rtnl_unlock();
1596 }
1597 }
1598 break;
1599 default: ldv_assume(0);
1600 }
1601 }
1602 }
1603 break;
1604 case 1:{
1605 /*DEG-struct: handlers from structure fops_wcn36xx_bmps*/
1606 /*DEG-CHECK: checking registration of fops_wcn36xx_bmps structure*/
1607 if(ldv_state_variable_4 != 0){
1608 ldv_main_exported_4();
1609 }
1610 }
1611 break;
1612 case 2:{
1613 /*DEG-struct: handlers from structure ldv_request_irq_1*/
1614 /*DEG-CHECK: checking registration of ldv_request_irq_1 structure*/
1615 if(ldv_state_variable_1 != 0){
1616 }
1617 }
1618 break;
1619 case 3:{
1620 /*DEG-struct: handlers from structure module*/
1621 /*DEG-CHECK: checking registration of module structure*/
1622 if(ldv_state_variable_0 != 0){
1623 switch(__VERIFIER_nondet_int()){
1624 case 0:{
1625 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1626 if(ldv_state_variable_0 == 2 && ref_cnt==0){
1627 /*DEG-CALL: handler module_exit from module*/
1628 wcn36xx_exit();
1629 ldv_state_variable_0 = 3;
1630 goto ldv_final;
1631 }
1632 }
1633 break;
1634 case 1:{
1635 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1636 if(ldv_state_variable_0 == 1){
1637 /*DEG-CALL: handler module_init from module*/
1638 ldv_retval_2=wcn36xx_init();
1639 if(ldv_retval_2!=0){
1640 ldv_state_variable_0 = 3;
1641 goto ldv_final;
1642 }
1643 /*DEG-postcall: if success*/
1644 if(ldv_retval_2==0){
1645 ldv_state_variable_0 = 2;
1646 ldv_state_variable_3 = 1;
1647 ldv_file_operations_3();
1648 ldv_state_variable_4 = 1;
1649 ldv_file_operations_4();
1650 }
1651 }
1652 }
1653 break;
1654 default: ldv_assume(0);
1655 }
1656 }
1657 }
1658 break;
1659 case 4:{
1660 /*DEG-struct: handlers from structure fops_wcn36xx_dump*/
1661 /*DEG-CHECK: checking registration of fops_wcn36xx_dump structure*/
1662 if(ldv_state_variable_3 != 0){
1663 ldv_main_exported_3();
1664 }
1665 }
1666 break;
1667 case 5:{
1668 /*DEG-struct: handlers from structure ldv_request_irq_0*/
1669 /*DEG-CHECK: checking registration of ldv_request_irq_0 structure*/
1670 if(ldv_state_variable_2 != 0){
1671 }
1672 }
1673 break;
1674 case 6:{
1675 /*DEG-struct: handlers from structure wcn36xx_driver*/
1676 /*DEG-CHECK: checking registration of wcn36xx_driver structure*/
1677 if(ldv_state_variable_5 != 0){
1678 switch(__VERIFIER_nondet_int()){
1679 case 0:{
1680 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1681 if(ldv_state_variable_5 == 1){
1682 /*DEG-CALL: handler probe from wcn36xx_driver*/
1683 ldv_retval_5=(& wcn36xx_probe)(wcn36xx_driver_group1);
1684 if(ldv_retval_5==0){
1685 ldv_state_variable_5 = 2;
1686 ref_cnt++;
1687 probed_5 = 1;
1688 }
1689 }
1690 }
1691 break;
1692 case 1:{
1693 /*DEG-state: state 1 (look at corresponding state-chart diagram for details)*/
1694 if(ldv_state_variable_5 == 1 && probed_5 == 1){
1695 /*DEG-CALL: handler remove from wcn36xx_driver*/
1696 ldv_retval_4=(& wcn36xx_remove)(wcn36xx_driver_group1);
1697 if(ldv_retval_4==0){
1698 ldv_state_variable_5 = 1;
1699 ref_cnt--;
1700 probed_5 = 0;
1701 }
1702 }
1703 /*DEG-state: state 2 (look at corresponding state-chart diagram for details)*/
1704 if(ldv_state_variable_5 == 2 && probed_5 == 1){
1705 /*DEG-CALL: handler remove from wcn36xx_driver*/
1706 ldv_retval_4=(& wcn36xx_remove)(wcn36xx_driver_group1);
1707 if(ldv_retval_4==0){
1708 ldv_state_variable_5 = 1;
1709 ref_cnt--;
1710 probed_5 = 0;
1711 }
1712 }
1713 }
1714 break;
1715 default: ldv_assume(0);
1716 }
1717 }
1718 }
1719 break;
1720 default: ldv_assume(0);
1721 }
1722 }
1723 ldv_final:
1724 ldv_check_final_state();
1725 return;
1726 }
1727 /* DEG-ENVIRONMENT-END */ 1 /*
2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include <linux/etherdevice.h>
20 #include <linux/firmware.h>
21 #include <linux/bitops.h>
22 #include "smd.h"
23
24 struct wcn36xx_cfg_val {
25 u32 cfg_id;
26 u32 value;
27 };
28
29 #define WCN36XX_CFG_VAL(id, val) \
30 { \
31 .cfg_id = WCN36XX_HAL_CFG_ ## id, \
32 .value = val \
33 }
34
35 static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
36 WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
37 WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
38 WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
39 WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
40 WCN36XX_CFG_VAL(CAL_PERIOD, 5),
41 WCN36XX_CFG_VAL(CAL_CONTROL, 1),
42 WCN36XX_CFG_VAL(PROXIMITY, 0),
43 WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
44 WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
45 WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
46 WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
47 WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 6),
48 WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 6),
49 WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
50 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
51 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
52 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
53 WCN36XX_CFG_VAL(FIXED_RATE, 0),
54 WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
55 WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
56 WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
57 WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
58 WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
59 WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
60 WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
61 WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
62 WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
63 WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
64 WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
65 WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
66 WCN36XX_CFG_VAL(STATS_PERIOD, 10),
67 WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
68 WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
69 WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
70 WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
71 WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
72 WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
73 WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
74 WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
75 WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
76 WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
77 };
78
79 static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
80 {
81 struct wcn36xx_hal_cfg *entry;
82 u32 *val;
83
84 if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
85 wcn36xx_err("Not enough room for TLV entry\n");
86 return -ENOMEM;
87 }
88
89 entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
90 entry->id = id;
91 entry->len = sizeof(u32);
92 entry->pad_bytes = 0;
93 entry->reserve = 0;
94
95 val = (u32 *) (entry + 1);
96 *val = value;
97
98 *len += sizeof(*entry) + sizeof(u32);
99
100 return 0;
101 }
102
103 static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
104 struct ieee80211_sta *sta,
105 struct wcn36xx_hal_config_bss_params *bss_params)
106 {
107 if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn))
108 bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
109 else if (sta && sta->ht_cap.ht_supported)
110 bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
111 else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f))
112 bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
113 else
114 bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
115 }
116
117 static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
118 {
119 return caps & flag ? 1 : 0;
120 }
121 static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
122 struct ieee80211_sta *sta,
123 struct wcn36xx_hal_config_bss_params *bss_params)
124 {
125 if (sta && sta->ht_cap.ht_supported) {
126 unsigned long caps = sta->ht_cap.cap;
127 bss_params->ht = sta->ht_cap.ht_supported;
128 bss_params->tx_channel_width_set = is_cap_supported(caps,
129 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
130 bss_params->lsig_tx_op_protection_full_support =
131 is_cap_supported(caps,
132 IEEE80211_HT_CAP_LSIG_TXOP_PROT);
133
134 bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
135 bss_params->lln_non_gf_coexist =
136 !!(vif->bss_conf.ht_operation_mode &
137 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
138 /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
139 bss_params->dual_cts_protection = 0;
140 /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
141 bss_params->ht20_coexist = 0;
142 }
143 }
144
145 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
146 struct wcn36xx_hal_config_sta_params *sta_params)
147 {
148 if (sta->ht_cap.ht_supported) {
149 unsigned long caps = sta->ht_cap.cap;
150 sta_params->ht_capable = sta->ht_cap.ht_supported;
151 sta_params->tx_channel_width_set = is_cap_supported(caps,
152 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
153 sta_params->lsig_txop_protection = is_cap_supported(caps,
154 IEEE80211_HT_CAP_LSIG_TXOP_PROT);
155
156 sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor;
157 sta_params->max_ampdu_density = sta->ht_cap.ampdu_density;
158 sta_params->max_amsdu_size = is_cap_supported(caps,
159 IEEE80211_HT_CAP_MAX_AMSDU);
160 sta_params->sgi_20Mhz = is_cap_supported(caps,
161 IEEE80211_HT_CAP_SGI_20);
162 sta_params->sgi_40mhz = is_cap_supported(caps,
163 IEEE80211_HT_CAP_SGI_40);
164 sta_params->green_field_capable = is_cap_supported(caps,
165 IEEE80211_HT_CAP_GRN_FLD);
166 sta_params->delayed_ba_support = is_cap_supported(caps,
167 IEEE80211_HT_CAP_DELAY_BA);
168 sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
169 IEEE80211_HT_CAP_DSSSCCK40);
170 }
171 }
172
173 static void wcn36xx_smd_set_sta_default_ht_params(
174 struct wcn36xx_hal_config_sta_params *sta_params)
175 {
176 sta_params->ht_capable = 1;
177 sta_params->tx_channel_width_set = 1;
178 sta_params->lsig_txop_protection = 1;
179 sta_params->max_ampdu_size = 3;
180 sta_params->max_ampdu_density = 5;
181 sta_params->max_amsdu_size = 0;
182 sta_params->sgi_20Mhz = 1;
183 sta_params->sgi_40mhz = 1;
184 sta_params->green_field_capable = 1;
185 sta_params->delayed_ba_support = 0;
186 sta_params->dsss_cck_mode_40mhz = 1;
187 }
188
189 static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
190 struct ieee80211_vif *vif,
191 struct ieee80211_sta *sta,
192 struct wcn36xx_hal_config_sta_params *sta_params)
193 {
194 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
195 struct wcn36xx_sta *priv_sta = NULL;
196 if (vif->type == NL80211_IFTYPE_ADHOC ||
197 vif->type == NL80211_IFTYPE_AP ||
198 vif->type == NL80211_IFTYPE_MESH_POINT) {
199 sta_params->type = 1;
200 sta_params->sta_index = 0xFF;
201 } else {
202 sta_params->type = 0;
203 sta_params->sta_index = 1;
204 }
205
206 sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
207
208 /*
209 * In STA mode ieee80211_sta contains bssid and ieee80211_vif
210 * contains our mac address. In AP mode we are bssid so vif
211 * contains bssid and ieee80211_sta contains mac.
212 */
213 if (NL80211_IFTYPE_STATION == vif->type)
214 memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
215 else
216 memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
217
218 sta_params->encrypt_type = priv_vif->encrypt_type;
219 sta_params->short_preamble_supported = true;
220
221 sta_params->rifs_mode = 0;
222 sta_params->rmf = 0;
223 sta_params->action = 0;
224 sta_params->uapsd = 0;
225 sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
226 sta_params->max_ampdu_duration = 0;
227 sta_params->bssid_index = priv_vif->bss_index;
228 sta_params->p2p = 0;
229
230 if (sta) {
231 priv_sta = (struct wcn36xx_sta *)sta->drv_priv;
232 if (NL80211_IFTYPE_STATION == vif->type)
233 memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
234 else
235 memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
236 sta_params->wmm_enabled = sta->wme;
237 sta_params->max_sp_len = sta->max_sp;
238 sta_params->aid = priv_sta->aid;
239 wcn36xx_smd_set_sta_ht_params(sta, sta_params);
240 memcpy(&sta_params->supported_rates, &priv_sta->supported_rates,
241 sizeof(priv_sta->supported_rates));
242 } else {
243 wcn36xx_set_default_rates(&sta_params->supported_rates);
244 wcn36xx_smd_set_sta_default_ht_params(sta_params);
245 }
246 }
247
248 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
249 {
250 int ret = 0;
251 unsigned long start;
252 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
253
254 init_completion(&wcn->hal_rsp_compl);
255 start = jiffies;
256 ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
257 if (ret) {
258 wcn36xx_err("HAL TX failed\n");
259 goto out;
260 }
261 if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
262 msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
263 wcn36xx_err("Timeout! No SMD response in %dms\n",
264 HAL_MSG_TIMEOUT);
265 ret = -ETIME;
266 goto out;
267 }
268 wcn36xx_dbg(WCN36XX_DBG_SMD, "SMD command completed in %dms",
269 jiffies_to_msecs(jiffies - start));
270 out:
271 return ret;
272 }
273
274 #define INIT_HAL_MSG(msg_body, type) \
275 do { \
276 memset(&msg_body, 0, sizeof(msg_body)); \
277 msg_body.header.msg_type = type; \
278 msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
279 msg_body.header.len = sizeof(msg_body); \
280 } while (0) \
281
282 #define PREPARE_HAL_BUF(send_buf, msg_body) \
283 do { \
284 memset(send_buf, 0, msg_body.header.len); \
285 memcpy(send_buf, &msg_body, sizeof(msg_body)); \
286 } while (0) \
287
288 static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
289 {
290 struct wcn36xx_fw_msg_status_rsp *rsp;
291
292 if (len < sizeof(struct wcn36xx_hal_msg_header) +
293 sizeof(struct wcn36xx_fw_msg_status_rsp))
294 return -EIO;
295
296 rsp = (struct wcn36xx_fw_msg_status_rsp *)
297 (buf + sizeof(struct wcn36xx_hal_msg_header));
298
299 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
300 return rsp->status;
301
302 return 0;
303 }
304
305 static int wcn36xx_smd_rsp_status_check_v2(struct wcn36xx *wcn, void *buf,
306 size_t len)
307 {
308 struct wcn36xx_fw_msg_status_rsp_v2 *rsp;
309
310 if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp))
311 return wcn36xx_smd_rsp_status_check(buf, len);
312
313 rsp = buf + sizeof(struct wcn36xx_hal_msg_header);
314
315 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
316 return rsp->status;
317
318 return 0;
319 }
320
321 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
322 {
323 struct nv_data *nv_d;
324 struct wcn36xx_hal_nv_img_download_req_msg msg_body;
325 int fw_bytes_left;
326 int ret;
327 u16 fm_offset = 0;
328
329 if (!wcn->nv) {
330 ret = request_firmware(&wcn->nv, WLAN_NV_FILE, wcn->dev);
331 if (ret) {
332 wcn36xx_err("Failed to load nv file %s: %d\n",
333 WLAN_NV_FILE, ret);
334 goto out;
335 }
336 }
337
338 nv_d = (struct nv_data *)wcn->nv->data;
339 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
340
341 msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
342
343 msg_body.frag_number = 0;
344 /* hal_buf must be protected with mutex */
345 mutex_lock(&wcn->hal_mutex);
346
347 do {
348 fw_bytes_left = wcn->nv->size - fm_offset - 4;
349 if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
350 msg_body.last_fragment = 0;
351 msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
352 } else {
353 msg_body.last_fragment = 1;
354 msg_body.nv_img_buffer_size = fw_bytes_left;
355
356 /* Do not forget update general message len */
357 msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
358
359 }
360
361 /* Add load NV request message header */
362 memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body));
363
364 /* Add NV body itself */
365 memcpy(wcn->hal_buf + sizeof(msg_body),
366 &nv_d->table + fm_offset,
367 msg_body.nv_img_buffer_size);
368
369 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
370 if (ret)
371 goto out_unlock;
372 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
373 wcn->hal_rsp_len);
374 if (ret) {
375 wcn36xx_err("hal_load_nv response failed err=%d\n",
376 ret);
377 goto out_unlock;
378 }
379 msg_body.frag_number++;
380 fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
381
382 } while (msg_body.last_fragment != 1);
383
384 out_unlock:
385 mutex_unlock(&wcn->hal_mutex);
386 out: return ret;
387 }
388
389 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
390 {
391 struct wcn36xx_hal_mac_start_rsp_msg *rsp;
392
393 if (len < sizeof(*rsp))
394 return -EIO;
395
396 rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf;
397
398 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
399 return -EIO;
400
401 memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
402 WCN36XX_HAL_VERSION_LENGTH);
403 memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
404 WCN36XX_HAL_VERSION_LENGTH);
405
406 /* null terminate the strings, just in case */
407 wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
408 wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
409
410 wcn->fw_revision = rsp->start_rsp_params.version.revision;
411 wcn->fw_version = rsp->start_rsp_params.version.version;
412 wcn->fw_minor = rsp->start_rsp_params.version.minor;
413 wcn->fw_major = rsp->start_rsp_params.version.major;
414
415 wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
416 wcn->wlan_version, wcn->crm_version);
417
418 wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
419 wcn->fw_major, wcn->fw_minor,
420 wcn->fw_version, wcn->fw_revision,
421 rsp->start_rsp_params.stations,
422 rsp->start_rsp_params.bssids);
423
424 return 0;
425 }
426
427 int wcn36xx_smd_start(struct wcn36xx *wcn)
428 {
429 struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
430 int ret = 0;
431 int i;
432 size_t len;
433
434 mutex_lock(&wcn->hal_mutex);
435 INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
436
437 msg_body.params.type = DRIVER_TYPE_PRODUCTION;
438 msg_body.params.len = 0;
439
440 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
441
442 body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
443 len = body->header.len;
444
445 for (i = 0; i < ARRAY_SIZE(wcn36xx_cfg_vals); i++) {
446 ret = put_cfg_tlv_u32(wcn, &len, wcn36xx_cfg_vals[i].cfg_id,
447 wcn36xx_cfg_vals[i].value);
448 if (ret)
449 goto out;
450 }
451 body->header.len = len;
452 body->params.len = len - sizeof(*body);
453
454 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
455 msg_body.params.type);
456
457 ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
458 if (ret) {
459 wcn36xx_err("Sending hal_start failed\n");
460 goto out;
461 }
462
463 ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
464 if (ret) {
465 wcn36xx_err("hal_start response failed err=%d\n", ret);
466 goto out;
467 }
468
469 out:
470 mutex_unlock(&wcn->hal_mutex);
471 return ret;
472 }
473
474 int wcn36xx_smd_stop(struct wcn36xx *wcn)
475 {
476 struct wcn36xx_hal_mac_stop_req_msg msg_body;
477 int ret = 0;
478
479 mutex_lock(&wcn->hal_mutex);
480 INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
481
482 msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
483
484 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
485
486 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
487 if (ret) {
488 wcn36xx_err("Sending hal_stop failed\n");
489 goto out;
490 }
491 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
492 if (ret) {
493 wcn36xx_err("hal_stop response failed err=%d\n", ret);
494 goto out;
495 }
496 out:
497 mutex_unlock(&wcn->hal_mutex);
498 return ret;
499 }
500
501 int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode)
502 {
503 struct wcn36xx_hal_init_scan_req_msg msg_body;
504 int ret = 0;
505
506 mutex_lock(&wcn->hal_mutex);
507 INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
508
509 msg_body.mode = mode;
510
511 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
512
513 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
514
515 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
516 if (ret) {
517 wcn36xx_err("Sending hal_init_scan failed\n");
518 goto out;
519 }
520 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
521 if (ret) {
522 wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
523 goto out;
524 }
525 out:
526 mutex_unlock(&wcn->hal_mutex);
527 return ret;
528 }
529
530 int wcn36xx_smd_start_scan(struct wcn36xx *wcn)
531 {
532 struct wcn36xx_hal_start_scan_req_msg msg_body;
533 int ret = 0;
534
535 mutex_lock(&wcn->hal_mutex);
536 INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
537
538 msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
539
540 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
541
542 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
543 msg_body.scan_channel);
544
545 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
546 if (ret) {
547 wcn36xx_err("Sending hal_start_scan failed\n");
548 goto out;
549 }
550 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
551 if (ret) {
552 wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
553 goto out;
554 }
555 out:
556 mutex_unlock(&wcn->hal_mutex);
557 return ret;
558 }
559
560 int wcn36xx_smd_end_scan(struct wcn36xx *wcn)
561 {
562 struct wcn36xx_hal_end_scan_req_msg msg_body;
563 int ret = 0;
564
565 mutex_lock(&wcn->hal_mutex);
566 INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
567
568 msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
569
570 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
571
572 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
573 msg_body.scan_channel);
574
575 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
576 if (ret) {
577 wcn36xx_err("Sending hal_end_scan failed\n");
578 goto out;
579 }
580 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
581 if (ret) {
582 wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
583 goto out;
584 }
585 out:
586 mutex_unlock(&wcn->hal_mutex);
587 return ret;
588 }
589
590 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
591 enum wcn36xx_hal_sys_mode mode)
592 {
593 struct wcn36xx_hal_finish_scan_req_msg msg_body;
594 int ret = 0;
595
596 mutex_lock(&wcn->hal_mutex);
597 INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
598
599 msg_body.mode = mode;
600
601 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
602
603 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
604 msg_body.mode);
605
606 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
607 if (ret) {
608 wcn36xx_err("Sending hal_finish_scan failed\n");
609 goto out;
610 }
611 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
612 if (ret) {
613 wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
614 goto out;
615 }
616 out:
617 mutex_unlock(&wcn->hal_mutex);
618 return ret;
619 }
620
621 static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
622 {
623 struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
624 int ret = 0;
625
626 ret = wcn36xx_smd_rsp_status_check(buf, len);
627 if (ret)
628 return ret;
629 rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf;
630 wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
631 rsp->channel_number, rsp->status);
632 return ret;
633 }
634
635 int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
636 struct ieee80211_vif *vif, int ch)
637 {
638 struct wcn36xx_hal_switch_channel_req_msg msg_body;
639 int ret = 0;
640
641 mutex_lock(&wcn->hal_mutex);
642 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
643
644 msg_body.channel_number = (u8)ch;
645 msg_body.tx_mgmt_power = 0xbf;
646 msg_body.max_tx_power = 0xbf;
647 memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
648
649 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
650
651 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
652 if (ret) {
653 wcn36xx_err("Sending hal_switch_channel failed\n");
654 goto out;
655 }
656 ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
657 if (ret) {
658 wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
659 goto out;
660 }
661 out:
662 mutex_unlock(&wcn->hal_mutex);
663 return ret;
664 }
665
666 static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
667 {
668 struct wcn36xx_hal_update_scan_params_resp *rsp;
669
670 rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf;
671
672 /* Remove the PNO version bit */
673 rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK));
674
675 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
676 wcn36xx_warn("error response from update scan\n");
677 return rsp->status;
678 }
679
680 return 0;
681 }
682
683 int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn)
684 {
685 struct wcn36xx_hal_update_scan_params_req msg_body;
686 int ret = 0;
687
688 mutex_lock(&wcn->hal_mutex);
689 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
690
691 msg_body.dot11d_enabled = 0;
692 msg_body.dot11d_resolved = 0;
693 msg_body.channel_count = 26;
694 msg_body.active_min_ch_time = 60;
695 msg_body.active_max_ch_time = 120;
696 msg_body.passive_min_ch_time = 60;
697 msg_body.passive_max_ch_time = 110;
698 msg_body.state = 0;
699
700 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
701
702 wcn36xx_dbg(WCN36XX_DBG_HAL,
703 "hal update scan params channel_count %d\n",
704 msg_body.channel_count);
705
706 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
707 if (ret) {
708 wcn36xx_err("Sending hal_update_scan_params failed\n");
709 goto out;
710 }
711 ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf,
712 wcn->hal_rsp_len);
713 if (ret) {
714 wcn36xx_err("hal_update_scan_params response failed err=%d\n",
715 ret);
716 goto out;
717 }
718 out:
719 mutex_unlock(&wcn->hal_mutex);
720 return ret;
721 }
722
723 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
724 struct ieee80211_vif *vif,
725 void *buf,
726 size_t len)
727 {
728 struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
729 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
730
731 if (len < sizeof(*rsp))
732 return -EINVAL;
733
734 rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf;
735
736 if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
737 wcn36xx_warn("hal add sta self failure: %d\n",
738 rsp->status);
739 return rsp->status;
740 }
741
742 wcn36xx_dbg(WCN36XX_DBG_HAL,
743 "hal add sta self status %d self_sta_index %d dpu_index %d\n",
744 rsp->status, rsp->self_sta_index, rsp->dpu_index);
745
746 priv_vif->self_sta_index = rsp->self_sta_index;
747 priv_vif->self_dpu_desc_index = rsp->dpu_index;
748
749 return 0;
750 }
751
752 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
753 {
754 struct wcn36xx_hal_add_sta_self_req msg_body;
755 int ret = 0;
756
757 mutex_lock(&wcn->hal_mutex);
758 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
759
760 memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
761
762 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
763
764 wcn36xx_dbg(WCN36XX_DBG_HAL,
765 "hal add sta self self_addr %pM status %d\n",
766 msg_body.self_addr, msg_body.status);
767
768 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
769 if (ret) {
770 wcn36xx_err("Sending hal_add_sta_self failed\n");
771 goto out;
772 }
773 ret = wcn36xx_smd_add_sta_self_rsp(wcn,
774 vif,
775 wcn->hal_buf,
776 wcn->hal_rsp_len);
777 if (ret) {
778 wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
779 goto out;
780 }
781 out:
782 mutex_unlock(&wcn->hal_mutex);
783 return ret;
784 }
785
786 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
787 {
788 struct wcn36xx_hal_del_sta_self_req_msg msg_body;
789 int ret = 0;
790
791 mutex_lock(&wcn->hal_mutex);
792 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
793
794 memcpy(&msg_body.self_addr, addr, ETH_ALEN);
795
796 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
797
798 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
799 if (ret) {
800 wcn36xx_err("Sending hal_delete_sta_self failed\n");
801 goto out;
802 }
803 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
804 if (ret) {
805 wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
806 ret);
807 goto out;
808 }
809 out:
810 mutex_unlock(&wcn->hal_mutex);
811 return ret;
812 }
813
814 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
815 {
816 struct wcn36xx_hal_delete_sta_req_msg msg_body;
817 int ret = 0;
818
819 mutex_lock(&wcn->hal_mutex);
820 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
821
822 msg_body.sta_index = sta_index;
823
824 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
825
826 wcn36xx_dbg(WCN36XX_DBG_HAL,
827 "hal delete sta sta_index %d\n",
828 msg_body.sta_index);
829
830 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
831 if (ret) {
832 wcn36xx_err("Sending hal_delete_sta failed\n");
833 goto out;
834 }
835 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
836 if (ret) {
837 wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
838 goto out;
839 }
840 out:
841 mutex_unlock(&wcn->hal_mutex);
842 return ret;
843 }
844
845 static int wcn36xx_smd_join_rsp(void *buf, size_t len)
846 {
847 struct wcn36xx_hal_join_rsp_msg *rsp;
848
849 if (wcn36xx_smd_rsp_status_check(buf, len))
850 return -EIO;
851
852 rsp = (struct wcn36xx_hal_join_rsp_msg *)buf;
853
854 wcn36xx_dbg(WCN36XX_DBG_HAL,
855 "hal rsp join status %d tx_mgmt_power %d\n",
856 rsp->status, rsp->tx_mgmt_power);
857
858 return 0;
859 }
860
861 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
862 {
863 struct wcn36xx_hal_join_req_msg msg_body;
864 int ret = 0;
865
866 mutex_lock(&wcn->hal_mutex);
867 INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
868
869 memcpy(&msg_body.bssid, bssid, ETH_ALEN);
870 memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
871 msg_body.channel = ch;
872
873 if (conf_is_ht40_minus(&wcn->hw->conf))
874 msg_body.secondary_channel_offset =
875 PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
876 else if (conf_is_ht40_plus(&wcn->hw->conf))
877 msg_body.secondary_channel_offset =
878 PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
879 else
880 msg_body.secondary_channel_offset =
881 PHY_SINGLE_CHANNEL_CENTERED;
882
883 msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
884
885 msg_body.max_tx_power = 0xbf;
886 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
887
888 wcn36xx_dbg(WCN36XX_DBG_HAL,
889 "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
890 msg_body.bssid, msg_body.self_sta_mac_addr,
891 msg_body.channel, msg_body.link_state);
892
893 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
894 if (ret) {
895 wcn36xx_err("Sending hal_join failed\n");
896 goto out;
897 }
898 ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
899 if (ret) {
900 wcn36xx_err("hal_join response failed err=%d\n", ret);
901 goto out;
902 }
903 out:
904 mutex_unlock(&wcn->hal_mutex);
905 return ret;
906 }
907
908 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
909 const u8 *sta_mac,
910 enum wcn36xx_hal_link_state state)
911 {
912 struct wcn36xx_hal_set_link_state_req_msg msg_body;
913 int ret = 0;
914
915 mutex_lock(&wcn->hal_mutex);
916 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
917
918 memcpy(&msg_body.bssid, bssid, ETH_ALEN);
919 memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
920 msg_body.state = state;
921
922 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
923
924 wcn36xx_dbg(WCN36XX_DBG_HAL,
925 "hal set link state bssid %pM self_mac_addr %pM state %d\n",
926 msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
927
928 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
929 if (ret) {
930 wcn36xx_err("Sending hal_set_link_st failed\n");
931 goto out;
932 }
933 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
934 if (ret) {
935 wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
936 goto out;
937 }
938 out:
939 mutex_unlock(&wcn->hal_mutex);
940 return ret;
941 }
942
943 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
944 const struct wcn36xx_hal_config_sta_params *orig,
945 struct wcn36xx_hal_config_sta_params_v1 *v1)
946 {
947 /* convert orig to v1 format */
948 memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
949 memcpy(&v1->mac, orig->mac, ETH_ALEN);
950 v1->aid = orig->aid;
951 v1->type = orig->type;
952 v1->listen_interval = orig->listen_interval;
953 v1->ht_capable = orig->ht_capable;
954
955 v1->max_ampdu_size = orig->max_ampdu_size;
956 v1->max_ampdu_density = orig->max_ampdu_density;
957 v1->sgi_40mhz = orig->sgi_40mhz;
958 v1->sgi_20Mhz = orig->sgi_20Mhz;
959
960 memcpy(&v1->supported_rates, &orig->supported_rates,
961 sizeof(orig->supported_rates));
962 v1->sta_index = orig->sta_index;
963 }
964
965 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
966 struct ieee80211_sta *sta,
967 void *buf,
968 size_t len)
969 {
970 struct wcn36xx_hal_config_sta_rsp_msg *rsp;
971 struct config_sta_rsp_params *params;
972 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
973
974 if (len < sizeof(*rsp))
975 return -EINVAL;
976
977 rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf;
978 params = &rsp->params;
979
980 if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
981 wcn36xx_warn("hal config sta response failure: %d\n",
982 params->status);
983 return -EIO;
984 }
985
986 sta_priv->sta_index = params->sta_index;
987 sta_priv->dpu_desc_index = params->dpu_index;
988 sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
989
990 wcn36xx_dbg(WCN36XX_DBG_HAL,
991 "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
992 params->status, params->sta_index, params->bssid_index,
993 params->uc_ucast_sig, params->p2p);
994
995 return 0;
996 }
997
998 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
999 const struct wcn36xx_hal_config_sta_req_msg *orig)
1000 {
1001 struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
1002 struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params;
1003
1004 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1005
1006 wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params,
1007 &msg_body.sta_params);
1008
1009 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1010
1011 wcn36xx_dbg(WCN36XX_DBG_HAL,
1012 "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1013 sta->action, sta->sta_index, sta->bssid_index,
1014 sta->bssid, sta->type, sta->mac, sta->aid);
1015
1016 return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1017 }
1018
1019 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1020 struct ieee80211_sta *sta)
1021 {
1022 struct wcn36xx_hal_config_sta_req_msg msg;
1023 struct wcn36xx_hal_config_sta_params *sta_params;
1024 int ret = 0;
1025
1026 mutex_lock(&wcn->hal_mutex);
1027 INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
1028
1029 sta_params = &msg.sta_params;
1030
1031 wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1032
1033 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1034 ret = wcn36xx_smd_config_sta_v1(wcn, &msg);
1035 } else {
1036 PREPARE_HAL_BUF(wcn->hal_buf, msg);
1037
1038 wcn36xx_dbg(WCN36XX_DBG_HAL,
1039 "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1040 sta_params->action, sta_params->sta_index,
1041 sta_params->bssid_index, sta_params->bssid,
1042 sta_params->type, sta_params->mac, sta_params->aid);
1043
1044 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1045 }
1046 if (ret) {
1047 wcn36xx_err("Sending hal_config_sta failed\n");
1048 goto out;
1049 }
1050 ret = wcn36xx_smd_config_sta_rsp(wcn,
1051 sta,
1052 wcn->hal_buf,
1053 wcn->hal_rsp_len);
1054 if (ret) {
1055 wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
1056 goto out;
1057 }
1058 out:
1059 mutex_unlock(&wcn->hal_mutex);
1060 return ret;
1061 }
1062
1063 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1064 const struct wcn36xx_hal_config_bss_req_msg *orig)
1065 {
1066 struct wcn36xx_hal_config_bss_req_msg_v1 msg_body;
1067 struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params;
1068 struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta;
1069
1070 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ);
1071
1072 /* convert orig to v1 */
1073 memcpy(&msg_body.bss_params.bssid,
1074 &orig->bss_params.bssid, ETH_ALEN);
1075 memcpy(&msg_body.bss_params.self_mac_addr,
1076 &orig->bss_params.self_mac_addr, ETH_ALEN);
1077
1078 msg_body.bss_params.bss_type = orig->bss_params.bss_type;
1079 msg_body.bss_params.oper_mode = orig->bss_params.oper_mode;
1080 msg_body.bss_params.nw_type = orig->bss_params.nw_type;
1081
1082 msg_body.bss_params.short_slot_time_supported =
1083 orig->bss_params.short_slot_time_supported;
1084 msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist;
1085 msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist;
1086 msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist;
1087 msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist;
1088 msg_body.bss_params.lln_non_gf_coexist =
1089 orig->bss_params.lln_non_gf_coexist;
1090
1091 msg_body.bss_params.lsig_tx_op_protection_full_support =
1092 orig->bss_params.lsig_tx_op_protection_full_support;
1093 msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode;
1094 msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval;
1095 msg_body.bss_params.dtim_period = orig->bss_params.dtim_period;
1096 msg_body.bss_params.tx_channel_width_set =
1097 orig->bss_params.tx_channel_width_set;
1098 msg_body.bss_params.oper_channel = orig->bss_params.oper_channel;
1099 msg_body.bss_params.ext_channel = orig->bss_params.ext_channel;
1100
1101 msg_body.bss_params.reserved = orig->bss_params.reserved;
1102
1103 memcpy(&msg_body.bss_params.ssid,
1104 &orig->bss_params.ssid,
1105 sizeof(orig->bss_params.ssid));
1106
1107 msg_body.bss_params.action = orig->bss_params.action;
1108 msg_body.bss_params.rateset = orig->bss_params.rateset;
1109 msg_body.bss_params.ht = orig->bss_params.ht;
1110 msg_body.bss_params.obss_prot_enabled =
1111 orig->bss_params.obss_prot_enabled;
1112 msg_body.bss_params.rmf = orig->bss_params.rmf;
1113 msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode;
1114 msg_body.bss_params.dual_cts_protection =
1115 orig->bss_params.dual_cts_protection;
1116
1117 msg_body.bss_params.max_probe_resp_retry_limit =
1118 orig->bss_params.max_probe_resp_retry_limit;
1119 msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid;
1120 msg_body.bss_params.proxy_probe_resp =
1121 orig->bss_params.proxy_probe_resp;
1122 msg_body.bss_params.edca_params_valid =
1123 orig->bss_params.edca_params_valid;
1124
1125 memcpy(&msg_body.bss_params.acbe,
1126 &orig->bss_params.acbe,
1127 sizeof(orig->bss_params.acbe));
1128 memcpy(&msg_body.bss_params.acbk,
1129 &orig->bss_params.acbk,
1130 sizeof(orig->bss_params.acbk));
1131 memcpy(&msg_body.bss_params.acvi,
1132 &orig->bss_params.acvi,
1133 sizeof(orig->bss_params.acvi));
1134 memcpy(&msg_body.bss_params.acvo,
1135 &orig->bss_params.acvo,
1136 sizeof(orig->bss_params.acvo));
1137
1138 msg_body.bss_params.ext_set_sta_key_param_valid =
1139 orig->bss_params.ext_set_sta_key_param_valid;
1140
1141 memcpy(&msg_body.bss_params.ext_set_sta_key_param,
1142 &orig->bss_params.ext_set_sta_key_param,
1143 sizeof(orig->bss_params.acvo));
1144
1145 msg_body.bss_params.wcn36xx_hal_persona =
1146 orig->bss_params.wcn36xx_hal_persona;
1147 msg_body.bss_params.spectrum_mgt_enable =
1148 orig->bss_params.spectrum_mgt_enable;
1149 msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power;
1150 msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power;
1151
1152 wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta,
1153 &msg_body.bss_params.sta);
1154
1155 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1156
1157 wcn36xx_dbg(WCN36XX_DBG_HAL,
1158 "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1159 bss->bssid, bss->self_mac_addr, bss->bss_type,
1160 bss->oper_mode, bss->nw_type);
1161
1162 wcn36xx_dbg(WCN36XX_DBG_HAL,
1163 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1164 sta->bssid, sta->action, sta->sta_index,
1165 sta->bssid_index, sta->aid, sta->type, sta->mac);
1166
1167 return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1168 }
1169
1170
1171 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1172 struct ieee80211_vif *vif,
1173 void *buf,
1174 size_t len)
1175 {
1176 struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1177 struct wcn36xx_hal_config_bss_rsp_params *params;
1178 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
1179
1180 if (len < sizeof(*rsp))
1181 return -EINVAL;
1182
1183 rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
1184 params = &rsp->bss_rsp_params;
1185
1186 if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1187 wcn36xx_warn("hal config bss response failure: %d\n",
1188 params->status);
1189 return -EIO;
1190 }
1191
1192 wcn36xx_dbg(WCN36XX_DBG_HAL,
1193 "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1194 " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1195 " power %d ucast_dpu_signature %d\n",
1196 params->status, params->bss_index, params->dpu_desc_index,
1197 params->bss_sta_index, params->bss_self_sta_index,
1198 params->bss_bcast_sta_idx, params->mac,
1199 params->tx_mgmt_power, params->ucast_dpu_signature);
1200
1201 priv_vif->bss_index = params->bss_index;
1202
1203 if (priv_vif->sta) {
1204 priv_vif->sta->bss_sta_index = params->bss_sta_index;
1205 priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index;
1206 }
1207
1208 priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature;
1209
1210 return 0;
1211 }
1212
1213 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1214 struct ieee80211_sta *sta, const u8 *bssid,
1215 bool update)
1216 {
1217 struct wcn36xx_hal_config_bss_req_msg msg;
1218 struct wcn36xx_hal_config_bss_params *bss;
1219 struct wcn36xx_hal_config_sta_params *sta_params;
1220 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1221 int ret = 0;
1222
1223 mutex_lock(&wcn->hal_mutex);
1224 INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ);
1225
1226 bss = &msg.bss_params;
1227 sta_params = &bss->sta;
1228
1229 WARN_ON(is_zero_ether_addr(bssid));
1230
1231 memcpy(&bss->bssid, bssid, ETH_ALEN);
1232
1233 memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1234
1235 if (vif->type == NL80211_IFTYPE_STATION) {
1236 bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1237
1238 /* STA */
1239 bss->oper_mode = 1;
1240 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1241 } else if (vif->type == NL80211_IFTYPE_AP ||
1242 vif->type == NL80211_IFTYPE_MESH_POINT) {
1243 bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1244
1245 /* AP */
1246 bss->oper_mode = 0;
1247 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1248 } else if (vif->type == NL80211_IFTYPE_ADHOC) {
1249 bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1250
1251 /* STA */
1252 bss->oper_mode = 1;
1253 } else {
1254 wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1255 }
1256
1257 if (vif->type == NL80211_IFTYPE_STATION)
1258 wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1259 else
1260 bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1261
1262 bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1263 bss->lla_coexist = 0;
1264 bss->llb_coexist = 0;
1265 bss->llg_coexist = 0;
1266 bss->rifs_mode = 0;
1267 bss->beacon_interval = vif->bss_conf.beacon_int;
1268 bss->dtim_period = vif_priv->dtim_period;
1269
1270 wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1271
1272 bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1273
1274 if (conf_is_ht40_minus(&wcn->hw->conf))
1275 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1276 else if (conf_is_ht40_plus(&wcn->hw->conf))
1277 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1278 else
1279 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1280
1281 bss->reserved = 0;
1282 wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1283
1284 /* wcn->ssid is only valid in AP and IBSS mode */
1285 bss->ssid.length = vif_priv->ssid.length;
1286 memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1287
1288 bss->obss_prot_enabled = 0;
1289 bss->rmf = 0;
1290 bss->max_probe_resp_retry_limit = 0;
1291 bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1292 bss->proxy_probe_resp = 0;
1293 bss->edca_params_valid = 0;
1294
1295 /* FIXME: set acbe, acbk, acvi and acvo */
1296
1297 bss->ext_set_sta_key_param_valid = 0;
1298
1299 /* FIXME: set ext_set_sta_key_param */
1300
1301 bss->spectrum_mgt_enable = 0;
1302 bss->tx_mgmt_power = 0;
1303 bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1304
1305 bss->action = update;
1306
1307 wcn36xx_dbg(WCN36XX_DBG_HAL,
1308 "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1309 bss->bssid, bss->self_mac_addr, bss->bss_type,
1310 bss->oper_mode, bss->nw_type);
1311
1312 wcn36xx_dbg(WCN36XX_DBG_HAL,
1313 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1314 sta_params->bssid, sta_params->action,
1315 sta_params->sta_index, sta_params->bssid_index,
1316 sta_params->aid, sta_params->type,
1317 sta_params->mac);
1318
1319 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1320 ret = wcn36xx_smd_config_bss_v1(wcn, &msg);
1321 } else {
1322 PREPARE_HAL_BUF(wcn->hal_buf, msg);
1323
1324 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1325 }
1326 if (ret) {
1327 wcn36xx_err("Sending hal_config_bss failed\n");
1328 goto out;
1329 }
1330 ret = wcn36xx_smd_config_bss_rsp(wcn,
1331 vif,
1332 wcn->hal_buf,
1333 wcn->hal_rsp_len);
1334 if (ret) {
1335 wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1336 goto out;
1337 }
1338 out:
1339 mutex_unlock(&wcn->hal_mutex);
1340 return ret;
1341 }
1342
1343 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1344 {
1345 struct wcn36xx_hal_delete_bss_req_msg msg_body;
1346 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
1347 int ret = 0;
1348
1349 mutex_lock(&wcn->hal_mutex);
1350 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1351
1352 msg_body.bss_index = priv_vif->bss_index;
1353
1354 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1355
1356 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1357
1358 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1359 if (ret) {
1360 wcn36xx_err("Sending hal_delete_bss failed\n");
1361 goto out;
1362 }
1363 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1364 if (ret) {
1365 wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1366 goto out;
1367 }
1368 out:
1369 mutex_unlock(&wcn->hal_mutex);
1370 return ret;
1371 }
1372
1373 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1374 struct sk_buff *skb_beacon, u16 tim_off,
1375 u16 p2p_off)
1376 {
1377 struct wcn36xx_hal_send_beacon_req_msg msg_body;
1378 int ret = 0;
1379
1380 mutex_lock(&wcn->hal_mutex);
1381 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1382
1383 /* TODO need to find out why this is needed? */
1384 msg_body.beacon_length = skb_beacon->len + 6;
1385
1386 if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) {
1387 memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32));
1388 memcpy(&(msg_body.beacon[4]), skb_beacon->data,
1389 skb_beacon->len);
1390 } else {
1391 wcn36xx_err("Beacon is to big: beacon size=%d\n",
1392 msg_body.beacon_length);
1393 ret = -ENOMEM;
1394 goto out;
1395 }
1396 memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1397
1398 /* TODO need to find out why this is needed? */
1399 if (vif->type == NL80211_IFTYPE_MESH_POINT)
1400 /* mesh beacon don't need this, so push further down */
1401 msg_body.tim_ie_offset = 256;
1402 else
1403 msg_body.tim_ie_offset = tim_off+4;
1404 msg_body.p2p_ie_offset = p2p_off;
1405 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1406
1407 wcn36xx_dbg(WCN36XX_DBG_HAL,
1408 "hal send beacon beacon_length %d\n",
1409 msg_body.beacon_length);
1410
1411 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1412 if (ret) {
1413 wcn36xx_err("Sending hal_send_beacon failed\n");
1414 goto out;
1415 }
1416 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1417 if (ret) {
1418 wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
1419 goto out;
1420 }
1421 out:
1422 mutex_unlock(&wcn->hal_mutex);
1423 return ret;
1424 }
1425
1426 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
1427 struct ieee80211_vif *vif,
1428 struct sk_buff *skb)
1429 {
1430 struct wcn36xx_hal_send_probe_resp_req_msg msg;
1431 int ret = 0;
1432
1433 mutex_lock(&wcn->hal_mutex);
1434 INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
1435
1436 if (skb->len > BEACON_TEMPLATE_SIZE) {
1437 wcn36xx_warn("probe response template is too big: %d\n",
1438 skb->len);
1439 ret = -E2BIG;
1440 goto out;
1441 }
1442
1443 msg.probe_resp_template_len = skb->len;
1444 memcpy(&msg.probe_resp_template, skb->data, skb->len);
1445
1446 memcpy(msg.bssid, vif->addr, ETH_ALEN);
1447
1448 PREPARE_HAL_BUF(wcn->hal_buf, msg);
1449
1450 wcn36xx_dbg(WCN36XX_DBG_HAL,
1451 "hal update probe rsp len %d bssid %pM\n",
1452 msg.probe_resp_template_len, msg.bssid);
1453
1454 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1455 if (ret) {
1456 wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
1457 goto out;
1458 }
1459 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1460 if (ret) {
1461 wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
1462 ret);
1463 goto out;
1464 }
1465 out:
1466 mutex_unlock(&wcn->hal_mutex);
1467 return ret;
1468 }
1469
1470 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
1471 enum ani_ed_type enc_type,
1472 u8 keyidx,
1473 u8 keylen,
1474 u8 *key,
1475 u8 sta_index)
1476 {
1477 struct wcn36xx_hal_set_sta_key_req_msg msg_body;
1478 int ret = 0;
1479
1480 mutex_lock(&wcn->hal_mutex);
1481 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
1482
1483 msg_body.set_sta_key_params.sta_index = sta_index;
1484 msg_body.set_sta_key_params.enc_type = enc_type;
1485
1486 msg_body.set_sta_key_params.key[0].id = keyidx;
1487 msg_body.set_sta_key_params.key[0].unicast = 1;
1488 msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
1489 msg_body.set_sta_key_params.key[0].pae_role = 0;
1490 msg_body.set_sta_key_params.key[0].length = keylen;
1491 memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
1492 msg_body.set_sta_key_params.single_tid_rc = 1;
1493
1494 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1495
1496 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1497 if (ret) {
1498 wcn36xx_err("Sending hal_set_stakey failed\n");
1499 goto out;
1500 }
1501 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1502 if (ret) {
1503 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
1504 goto out;
1505 }
1506 out:
1507 mutex_unlock(&wcn->hal_mutex);
1508 return ret;
1509 }
1510
1511 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
1512 enum ani_ed_type enc_type,
1513 u8 keyidx,
1514 u8 keylen,
1515 u8 *key)
1516 {
1517 struct wcn36xx_hal_set_bss_key_req_msg msg_body;
1518 int ret = 0;
1519
1520 mutex_lock(&wcn->hal_mutex);
1521 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
1522 msg_body.bss_idx = 0;
1523 msg_body.enc_type = enc_type;
1524 msg_body.num_keys = 1;
1525 msg_body.keys[0].id = keyidx;
1526 msg_body.keys[0].unicast = 0;
1527 msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
1528 msg_body.keys[0].pae_role = 0;
1529 msg_body.keys[0].length = keylen;
1530 memcpy(msg_body.keys[0].key, key, keylen);
1531
1532 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1533
1534 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1535 if (ret) {
1536 wcn36xx_err("Sending hal_set_bsskey failed\n");
1537 goto out;
1538 }
1539 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1540 if (ret) {
1541 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
1542 goto out;
1543 }
1544 out:
1545 mutex_unlock(&wcn->hal_mutex);
1546 return ret;
1547 }
1548
1549 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
1550 enum ani_ed_type enc_type,
1551 u8 keyidx,
1552 u8 sta_index)
1553 {
1554 struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
1555 int ret = 0;
1556
1557 mutex_lock(&wcn->hal_mutex);
1558 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
1559
1560 msg_body.sta_idx = sta_index;
1561 msg_body.enc_type = enc_type;
1562 msg_body.key_id = keyidx;
1563
1564 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1565
1566 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1567 if (ret) {
1568 wcn36xx_err("Sending hal_remove_stakey failed\n");
1569 goto out;
1570 }
1571 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1572 if (ret) {
1573 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
1574 goto out;
1575 }
1576 out:
1577 mutex_unlock(&wcn->hal_mutex);
1578 return ret;
1579 }
1580
1581 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
1582 enum ani_ed_type enc_type,
1583 u8 keyidx)
1584 {
1585 struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
1586 int ret = 0;
1587
1588 mutex_lock(&wcn->hal_mutex);
1589 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
1590 msg_body.bss_idx = 0;
1591 msg_body.enc_type = enc_type;
1592 msg_body.key_id = keyidx;
1593
1594 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1595
1596 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1597 if (ret) {
1598 wcn36xx_err("Sending hal_remove_bsskey failed\n");
1599 goto out;
1600 }
1601 ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
1602 wcn->hal_rsp_len);
1603 if (ret) {
1604 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
1605 goto out;
1606 }
1607 out:
1608 mutex_unlock(&wcn->hal_mutex);
1609 return ret;
1610 }
1611
1612 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1613 {
1614 struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1615 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1616 int ret = 0;
1617
1618 mutex_lock(&wcn->hal_mutex);
1619 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
1620
1621 msg_body.bss_index = vif_priv->bss_index;
1622 msg_body.tbtt = vif->bss_conf.sync_tsf;
1623 msg_body.dtim_period = vif_priv->dtim_period;
1624
1625 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1626
1627 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1628 if (ret) {
1629 wcn36xx_err("Sending hal_enter_bmps failed\n");
1630 goto out;
1631 }
1632 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1633 if (ret) {
1634 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
1635 goto out;
1636 }
1637 out:
1638 mutex_unlock(&wcn->hal_mutex);
1639 return ret;
1640 }
1641
1642 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1643 {
1644 struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1645 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1646 int ret = 0;
1647
1648 mutex_lock(&wcn->hal_mutex);
1649 INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
1650
1651 msg_body.bss_index = vif_priv->bss_index;
1652
1653 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1654
1655 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1656 if (ret) {
1657 wcn36xx_err("Sending hal_exit_bmps failed\n");
1658 goto out;
1659 }
1660 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1661 if (ret) {
1662 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
1663 goto out;
1664 }
1665 out:
1666 mutex_unlock(&wcn->hal_mutex);
1667 return ret;
1668 }
1669 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
1670 {
1671 struct wcn36xx_hal_set_power_params_req_msg msg_body;
1672 int ret = 0;
1673
1674 mutex_lock(&wcn->hal_mutex);
1675 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
1676
1677 /*
1678 * When host is down ignore every second dtim
1679 */
1680 if (ignore_dtim) {
1681 msg_body.ignore_dtim = 1;
1682 msg_body.dtim_period = 2;
1683 }
1684 msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
1685
1686 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1687
1688 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1689 if (ret) {
1690 wcn36xx_err("Sending hal_set_power_params failed\n");
1691 goto out;
1692 }
1693
1694 out:
1695 mutex_unlock(&wcn->hal_mutex);
1696 return ret;
1697 }
1698 /* Notice: This function should be called after associated, or else it
1699 * will be invalid
1700 */
1701 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
1702 struct ieee80211_vif *vif,
1703 int packet_type)
1704 {
1705 struct wcn36xx_hal_keep_alive_req_msg msg_body;
1706 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1707 int ret = 0;
1708
1709 mutex_lock(&wcn->hal_mutex);
1710 INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
1711
1712 if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
1713 msg_body.bss_index = vif_priv->bss_index;
1714 msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
1715 msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
1716 } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
1717 /* TODO: it also support ARP response type */
1718 } else {
1719 wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
1720 ret = -EINVAL;
1721 goto out;
1722 }
1723
1724 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1725
1726 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1727 if (ret) {
1728 wcn36xx_err("Sending hal_keep_alive failed\n");
1729 goto out;
1730 }
1731 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1732 if (ret) {
1733 wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
1734 goto out;
1735 }
1736 out:
1737 mutex_unlock(&wcn->hal_mutex);
1738 return ret;
1739 }
1740
1741 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
1742 u32 arg3, u32 arg4, u32 arg5)
1743 {
1744 struct wcn36xx_hal_dump_cmd_req_msg msg_body;
1745 int ret = 0;
1746
1747 mutex_lock(&wcn->hal_mutex);
1748 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
1749
1750 msg_body.arg1 = arg1;
1751 msg_body.arg2 = arg2;
1752 msg_body.arg3 = arg3;
1753 msg_body.arg4 = arg4;
1754 msg_body.arg5 = arg5;
1755
1756 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1757
1758 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1759 if (ret) {
1760 wcn36xx_err("Sending hal_dump_cmd failed\n");
1761 goto out;
1762 }
1763 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1764 if (ret) {
1765 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
1766 goto out;
1767 }
1768 out:
1769 mutex_unlock(&wcn->hal_mutex);
1770 return ret;
1771 }
1772
1773 void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
1774 {
1775 int arr_idx, bit_idx;
1776
1777 if (cap < 0 || cap > 127) {
1778 wcn36xx_warn("error cap idx %d\n", cap);
1779 return;
1780 }
1781
1782 arr_idx = cap / 32;
1783 bit_idx = cap % 32;
1784 bitmap[arr_idx] |= (1 << bit_idx);
1785 }
1786
1787 int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
1788 {
1789 int arr_idx, bit_idx;
1790 int ret = 0;
1791
1792 if (cap < 0 || cap > 127) {
1793 wcn36xx_warn("error cap idx %d\n", cap);
1794 return -EINVAL;
1795 }
1796
1797 arr_idx = cap / 32;
1798 bit_idx = cap % 32;
1799 ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0;
1800 return ret;
1801 }
1802
1803 void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
1804 {
1805 int arr_idx, bit_idx;
1806
1807 if (cap < 0 || cap > 127) {
1808 wcn36xx_warn("error cap idx %d\n", cap);
1809 return;
1810 }
1811
1812 arr_idx = cap / 32;
1813 bit_idx = cap % 32;
1814 bitmap[arr_idx] &= ~(1 << bit_idx);
1815 }
1816
1817 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
1818 {
1819 struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
1820 int ret = 0, i;
1821
1822 mutex_lock(&wcn->hal_mutex);
1823 INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
1824
1825 set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
1826
1827 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1828
1829 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1830 if (ret) {
1831 wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
1832 goto out;
1833 }
1834 if (wcn->hal_rsp_len != sizeof(*rsp)) {
1835 wcn36xx_err("Invalid hal_feature_caps_exchange response");
1836 goto out;
1837 }
1838
1839 rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
1840
1841 for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
1842 wcn->fw_feat_caps[i] = rsp->feat_caps[i];
1843 out:
1844 mutex_unlock(&wcn->hal_mutex);
1845 return ret;
1846 }
1847
1848 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
1849 struct ieee80211_sta *sta,
1850 u16 tid,
1851 u16 *ssn,
1852 u8 direction,
1853 u8 sta_index)
1854 {
1855 struct wcn36xx_hal_add_ba_session_req_msg msg_body;
1856 int ret = 0;
1857
1858 mutex_lock(&wcn->hal_mutex);
1859 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
1860
1861 msg_body.sta_index = sta_index;
1862 memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
1863 msg_body.dialog_token = 0x10;
1864 msg_body.tid = tid;
1865
1866 /* Immediate BA because Delayed BA is not supported */
1867 msg_body.policy = 1;
1868 msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
1869 msg_body.timeout = 0;
1870 if (ssn)
1871 msg_body.ssn = *ssn;
1872 msg_body.direction = direction;
1873
1874 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1875
1876 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1877 if (ret) {
1878 wcn36xx_err("Sending hal_add_ba_session failed\n");
1879 goto out;
1880 }
1881 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1882 if (ret) {
1883 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
1884 goto out;
1885 }
1886 out:
1887 mutex_unlock(&wcn->hal_mutex);
1888 return ret;
1889 }
1890
1891 int wcn36xx_smd_add_ba(struct wcn36xx *wcn)
1892 {
1893 struct wcn36xx_hal_add_ba_req_msg msg_body;
1894 int ret = 0;
1895
1896 mutex_lock(&wcn->hal_mutex);
1897 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
1898
1899 msg_body.session_id = 0;
1900 msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
1901
1902 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1903
1904 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1905 if (ret) {
1906 wcn36xx_err("Sending hal_add_ba failed\n");
1907 goto out;
1908 }
1909 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1910 if (ret) {
1911 wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
1912 goto out;
1913 }
1914 out:
1915 mutex_unlock(&wcn->hal_mutex);
1916 return ret;
1917 }
1918
1919 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index)
1920 {
1921 struct wcn36xx_hal_del_ba_req_msg msg_body;
1922 int ret = 0;
1923
1924 mutex_lock(&wcn->hal_mutex);
1925 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
1926
1927 msg_body.sta_index = sta_index;
1928 msg_body.tid = tid;
1929 msg_body.direction = 0;
1930 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1931
1932 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1933 if (ret) {
1934 wcn36xx_err("Sending hal_del_ba failed\n");
1935 goto out;
1936 }
1937 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1938 if (ret) {
1939 wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
1940 goto out;
1941 }
1942 out:
1943 mutex_unlock(&wcn->hal_mutex);
1944 return ret;
1945 }
1946
1947 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
1948 {
1949 struct wcn36xx_hal_trigger_ba_req_msg msg_body;
1950 struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
1951 int ret = 0;
1952
1953 mutex_lock(&wcn->hal_mutex);
1954 INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
1955
1956 msg_body.session_id = 0;
1957 msg_body.candidate_cnt = 1;
1958 msg_body.header.len += sizeof(*candidate);
1959 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1960
1961 candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
1962 (wcn->hal_buf + sizeof(msg_body));
1963 candidate->sta_index = sta_index;
1964 candidate->tid_bitmap = 1;
1965
1966 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1967 if (ret) {
1968 wcn36xx_err("Sending hal_trigger_ba failed\n");
1969 goto out;
1970 }
1971 ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
1972 wcn->hal_rsp_len);
1973 if (ret) {
1974 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
1975 goto out;
1976 }
1977 out:
1978 mutex_unlock(&wcn->hal_mutex);
1979 return ret;
1980 }
1981
1982 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
1983 {
1984 struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
1985
1986 if (len != sizeof(*rsp)) {
1987 wcn36xx_warn("Bad TX complete indication\n");
1988 return -EIO;
1989 }
1990
1991 wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
1992
1993 return 0;
1994 }
1995
1996 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
1997 void *buf,
1998 size_t len)
1999 {
2000 struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
2001 struct ieee80211_vif *vif = NULL;
2002 struct wcn36xx_vif *tmp;
2003
2004 /* Old FW does not have bss index */
2005 if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
2006 list_for_each_entry(tmp, &wcn->vif_list, list) {
2007 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2008 tmp->bss_index);
2009 vif = container_of((void *)tmp,
2010 struct ieee80211_vif,
2011 drv_priv);
2012 ieee80211_connection_loss(vif);
2013 }
2014 return 0;
2015 }
2016
2017 if (len != sizeof(*rsp)) {
2018 wcn36xx_warn("Corrupted missed beacon indication\n");
2019 return -EIO;
2020 }
2021
2022 list_for_each_entry(tmp, &wcn->vif_list, list) {
2023 if (tmp->bss_index == rsp->bss_index) {
2024 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2025 rsp->bss_index);
2026 vif = container_of((void *)tmp,
2027 struct ieee80211_vif,
2028 drv_priv);
2029 ieee80211_connection_loss(vif);
2030 return 0;
2031 }
2032 }
2033
2034 wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
2035 return -ENOENT;
2036 }
2037
2038 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2039 void *buf,
2040 size_t len)
2041 {
2042 struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2043 struct wcn36xx_vif *tmp;
2044 struct ieee80211_sta *sta = NULL;
2045
2046 if (len != sizeof(*rsp)) {
2047 wcn36xx_warn("Corrupted delete sta indication\n");
2048 return -EIO;
2049 }
2050
2051 list_for_each_entry(tmp, &wcn->vif_list, list) {
2052 if (sta && (tmp->sta->sta_index == rsp->sta_id)) {
2053 sta = container_of((void *)tmp->sta,
2054 struct ieee80211_sta,
2055 drv_priv);
2056 wcn36xx_dbg(WCN36XX_DBG_HAL,
2057 "delete station indication %pM index %d\n",
2058 rsp->addr2,
2059 rsp->sta_id);
2060 ieee80211_report_low_ack(sta, 0);
2061 return 0;
2062 }
2063 }
2064
2065 wcn36xx_warn("STA with addr %pM and index %d not found\n",
2066 rsp->addr2,
2067 rsp->sta_id);
2068 return -ENOENT;
2069 }
2070
2071 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
2072 {
2073 struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
2074 size_t len;
2075 int ret = 0;
2076
2077 mutex_lock(&wcn->hal_mutex);
2078 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
2079
2080 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2081
2082 body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
2083 len = msg_body.header.len;
2084
2085 put_cfg_tlv_u32(wcn, &len, cfg_id, value);
2086 body->header.len = len;
2087 body->len = len - sizeof(*body);
2088
2089 ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
2090 if (ret) {
2091 wcn36xx_err("Sending hal_update_cfg failed\n");
2092 goto out;
2093 }
2094 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2095 if (ret) {
2096 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
2097 goto out;
2098 }
2099 out:
2100 mutex_unlock(&wcn->hal_mutex);
2101 return ret;
2102 }
2103 static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
2104 {
2105 struct wcn36xx_hal_msg_header *msg_header = buf;
2106 struct wcn36xx_hal_ind_msg *msg_ind;
2107 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
2108
2109 switch (msg_header->msg_type) {
2110 case WCN36XX_HAL_START_RSP:
2111 case WCN36XX_HAL_CONFIG_STA_RSP:
2112 case WCN36XX_HAL_CONFIG_BSS_RSP:
2113 case WCN36XX_HAL_ADD_STA_SELF_RSP:
2114 case WCN36XX_HAL_STOP_RSP:
2115 case WCN36XX_HAL_DEL_STA_SELF_RSP:
2116 case WCN36XX_HAL_DELETE_STA_RSP:
2117 case WCN36XX_HAL_INIT_SCAN_RSP:
2118 case WCN36XX_HAL_START_SCAN_RSP:
2119 case WCN36XX_HAL_END_SCAN_RSP:
2120 case WCN36XX_HAL_FINISH_SCAN_RSP:
2121 case WCN36XX_HAL_DOWNLOAD_NV_RSP:
2122 case WCN36XX_HAL_DELETE_BSS_RSP:
2123 case WCN36XX_HAL_SEND_BEACON_RSP:
2124 case WCN36XX_HAL_SET_LINK_ST_RSP:
2125 case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
2126 case WCN36XX_HAL_SET_BSSKEY_RSP:
2127 case WCN36XX_HAL_SET_STAKEY_RSP:
2128 case WCN36XX_HAL_RMV_STAKEY_RSP:
2129 case WCN36XX_HAL_RMV_BSSKEY_RSP:
2130 case WCN36XX_HAL_ENTER_BMPS_RSP:
2131 case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
2132 case WCN36XX_HAL_EXIT_BMPS_RSP:
2133 case WCN36XX_HAL_KEEP_ALIVE_RSP:
2134 case WCN36XX_HAL_DUMP_COMMAND_RSP:
2135 case WCN36XX_HAL_ADD_BA_SESSION_RSP:
2136 case WCN36XX_HAL_ADD_BA_RSP:
2137 case WCN36XX_HAL_DEL_BA_RSP:
2138 case WCN36XX_HAL_TRIGGER_BA_RSP:
2139 case WCN36XX_HAL_UPDATE_CFG_RSP:
2140 case WCN36XX_HAL_JOIN_RSP:
2141 case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
2142 case WCN36XX_HAL_CH_SWITCH_RSP:
2143 case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
2144 memcpy(wcn->hal_buf, buf, len);
2145 wcn->hal_rsp_len = len;
2146 complete(&wcn->hal_rsp_compl);
2147 break;
2148
2149 case WCN36XX_HAL_COEX_IND:
2150 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
2151 case WCN36XX_HAL_OTA_TX_COMPL_IND:
2152 case WCN36XX_HAL_MISSED_BEACON_IND:
2153 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2154 msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
2155 if (!msg_ind)
2156 goto nomem;
2157 msg_ind->msg_len = len;
2158 msg_ind->msg = kmemdup(buf, len, GFP_KERNEL);
2159 if (!msg_ind->msg) {
2160 kfree(msg_ind);
2161 nomem:
2162 /*
2163 * FIXME: Do something smarter then just
2164 * printing an error.
2165 */
2166 wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
2167 msg_header->msg_type);
2168 break;
2169 }
2170 mutex_lock(&wcn->hal_ind_mutex);
2171 list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
2172 queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
2173 mutex_unlock(&wcn->hal_ind_mutex);
2174 wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
2175 break;
2176 default:
2177 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2178 msg_header->msg_type);
2179 }
2180 }
2181 static void wcn36xx_ind_smd_work(struct work_struct *work)
2182 {
2183 struct wcn36xx *wcn =
2184 container_of(work, struct wcn36xx, hal_ind_work);
2185 struct wcn36xx_hal_msg_header *msg_header;
2186 struct wcn36xx_hal_ind_msg *hal_ind_msg;
2187
2188 mutex_lock(&wcn->hal_ind_mutex);
2189
2190 hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
2191 struct wcn36xx_hal_ind_msg,
2192 list);
2193
2194 msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
2195
2196 switch (msg_header->msg_type) {
2197 case WCN36XX_HAL_COEX_IND:
2198 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
2199 break;
2200 case WCN36XX_HAL_OTA_TX_COMPL_IND:
2201 wcn36xx_smd_tx_compl_ind(wcn,
2202 hal_ind_msg->msg,
2203 hal_ind_msg->msg_len);
2204 break;
2205 case WCN36XX_HAL_MISSED_BEACON_IND:
2206 wcn36xx_smd_missed_beacon_ind(wcn,
2207 hal_ind_msg->msg,
2208 hal_ind_msg->msg_len);
2209 break;
2210 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2211 wcn36xx_smd_delete_sta_context_ind(wcn,
2212 hal_ind_msg->msg,
2213 hal_ind_msg->msg_len);
2214 break;
2215 default:
2216 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2217 msg_header->msg_type);
2218 }
2219 list_del(wcn->hal_ind_queue.next);
2220 kfree(hal_ind_msg->msg);
2221 kfree(hal_ind_msg);
2222 mutex_unlock(&wcn->hal_ind_mutex);
2223 }
2224 int wcn36xx_smd_open(struct wcn36xx *wcn)
2225 {
2226 int ret = 0;
2227 wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
2228 if (!wcn->hal_ind_wq) {
2229 wcn36xx_err("failed to allocate wq\n");
2230 ret = -ENOMEM;
2231 goto out;
2232 }
2233 INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
2234 INIT_LIST_HEAD(&wcn->hal_ind_queue);
2235 mutex_init(&wcn->hal_ind_mutex);
2236
2237 ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
2238 if (ret) {
2239 wcn36xx_err("failed to open control channel\n");
2240 goto free_wq;
2241 }
2242
2243 return ret;
2244
2245 free_wq:
2246 destroy_workqueue(wcn->hal_ind_wq);
2247 out:
2248 return ret;
2249 }
2250
2251 void wcn36xx_smd_close(struct wcn36xx *wcn)
2252 {
2253 wcn->ctrl_ops->close();
2254 destroy_workqueue(wcn->hal_ind_wq);
2255 mutex_destroy(&wcn->hal_ind_mutex);
2256 } 1
2 #include <linux/kernel.h>
3 #include <linux/mutex.h>
4 #include <linux/spinlock.h>
5 #include <linux/errno.h>
6 #include <verifier/rcv.h>
7 #include <linux/list.h>
8
9 /* mutexes */
10 extern int mutex_lock_interruptible(struct mutex *lock);
11 extern int mutex_lock_killable(struct mutex *lock);
12 extern void mutex_lock(struct mutex *lock);
13
14 /* mutex model functions */
15 extern void ldv_mutex_lock(struct mutex *lock, char *sign);
16 extern int ldv_mutex_is_locked(struct mutex *lock, char *sign);
17 extern void ldv_mutex_unlock(struct mutex *lock, char *sign);
18
19
20 /* Spin locks */
21 extern void __ldv_spin_lock(spinlock_t *lock);
22 extern void __ldv_spin_unlock(spinlock_t *lock);
23 extern int __ldv_spin_trylock(spinlock_t *lock);
24 extern void __ldv_spin_unlock_wait(spinlock_t *lock);
25 extern void __ldv_spin_can_lock(spinlock_t *lock);
26 extern int __ldv_atomic_dec_and_lock(spinlock_t *lock);
27
28 /* spin model functions */
29 extern void ldv_spin_lock(spinlock_t *lock, char *sign);
30 extern void ldv_spin_unlock(spinlock_t *lock, char *sign);
31 extern int ldv_spin_is_locked(spinlock_t *lock, char *sign);
32
33 /* Support for list binder functions */
34 static inline struct list_head *ldv_list_get_first(struct list_head *head) {
35 return head->next;
36 }
37
38 static inline int ldv_list_is_stop(struct list_head *pos, struct list_head *head) {
39 return pos==head;
40 }
41
42 static inline struct list_head *ldv_list_get_next(struct list_head *pos) {
43 return pos->next;
44 }
45
46 #include <linux/mutex.h>
47 #include <linux/slab.h>
48 #include <linux/irqreturn.h>
49 #include <verifier/rcv.h>
50 #include <linux/rtnetlink.h>
51 #include <linux/gfp.h>
52 extern void* ldv_irq_data_2_1;
53 extern int ldv_irq_1_3=0;
54 extern int ldv_irq_line_2_2;
55 extern void* ldv_irq_data_1_1;
56 extern int ldv_irq_1_0=0;
57 extern int probed_5=0;
58 extern struct file *fops_wcn36xx_bmps_group2;
59 extern int ldv_state_variable_6;
60 extern void* ldv_irq_data_1_0;
61 extern int ldv_state_variable_0;
62 extern int ldv_state_variable_5;
63 extern int ldv_irq_line_2_1;
64 extern int ldv_state_variable_2;
65 extern int ldv_irq_2_0=0;
66 extern void* ldv_irq_data_1_3;
67 extern void* ldv_irq_data_1_2;
68 extern struct file *fops_wcn36xx_dump_group2;
69 extern void* ldv_irq_data_2_0;
70 extern struct inode *fops_wcn36xx_dump_group1;
71 extern int ldv_irq_1_2=0;
72 extern int LDV_IN_INTERRUPT = 1;
73 extern int ldv_irq_1_1=0;
74 extern int ldv_irq_2_3=0;
75 extern void* ldv_irq_data_2_3;
76 extern int ldv_irq_line_1_3;
77 extern int ldv_irq_2_2=0;
78 extern struct mutex fs_mutex;
79 extern int ldv_irq_line_2_0;
80 extern int ldv_state_variable_3;
81 extern int ldv_irq_line_1_0;
82 extern struct platform_device *wcn36xx_driver_group1;
83 extern struct mutex ar_mutex;
84 extern int ref_cnt;
85 extern struct mutex key_mtx;
86 extern int ldv_irq_line_1_1;
87 extern void* ldv_irq_data_2_2;
88 extern struct ieee80211_hw *wcn36xx_ops_group0;
89 extern int ldv_state_variable_1;
90 extern struct inode *fops_wcn36xx_bmps_group1;
91 extern int ldv_irq_line_1_2;
92 extern int ldv_state_variable_4;
93 extern int ldv_irq_line_2_3;
94 extern int ldv_irq_2_1=0;
95 extern void ldv_initialyze_ieee80211_ops_6(void);
96 extern int evil_hack_key_6(void);
97 extern void ldv_file_operations_3(void);
98 extern void choose_interrupt_2(void);
99 extern void disable_suitable_irq_2(int line, void * data);
100 extern int evil_hack_6(void);
101 extern void ldv_platform_probe_5(int (*probe)(struct platform_device *));
102 extern void activate_suitable_irq_2(int line, void * data);
103 extern void disable_suitable_irq_1(int line, void * data);
104 extern int reg_check_1(irqreturn_t (*handler)(int, void *));
105 extern void activate_suitable_irq_1(int line, void * data);
106 extern int ldv_irq_1(int state, int line, void *data);
107 extern int evil_hack_fs_lock(void);
108 extern int __VERIFIER_nondet_int(void);
109 extern void ldv_platform_driver_init_5(void);
110 extern int ldv_irq_2(int state, int line, void *data);
111 extern int evil_hack_ar_lock(void);
112 extern void choose_interrupt_1(void);
113 extern int reg_check_2(irqreturn_t (*handler)(int, void *));
114 extern void ldv_file_operations_4(void);
115 #line 1 "/work/ldvuser/andrianov/work/current--X--drivers/net/wireless/ath/wcn36xx/--X--defaultlinux-4.5-rc7--X--races--X--cpachecker/linux-4.5-rc7/csd_deg_dscv/19/dscv_tempdir/dscv/ri/races/drivers/net/wireless/ath/wcn36xx/smd.c"
116 /*
117 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
118 *
119 * Permission to use, copy, modify, and/or distribute this software for any
120 * purpose with or without fee is hereby granted, provided that the above
121 * copyright notice and this permission notice appear in all copies.
122 *
123 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
124 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
125 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
126 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
127 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
128 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
129 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
130 */
131
132 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
133
134 #include <linux/etherdevice.h>
135 #include <linux/firmware.h>
136 #include <linux/bitops.h>
137 #include "smd.h"
138
139 struct wcn36xx_cfg_val {
140 u32 cfg_id;
141 u32 value;
142 };
143
144 #define WCN36XX_CFG_VAL(id, val) \
145 { \
146 .cfg_id = WCN36XX_HAL_CFG_ ## id, \
147 .value = val \
148 }
149
150 static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
151 WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
152 WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
153 WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
154 WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
155 WCN36XX_CFG_VAL(CAL_PERIOD, 5),
156 WCN36XX_CFG_VAL(CAL_CONTROL, 1),
157 WCN36XX_CFG_VAL(PROXIMITY, 0),
158 WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
159 WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
160 WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
161 WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
162 WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 6),
163 WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 6),
164 WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
165 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
166 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
167 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
168 WCN36XX_CFG_VAL(FIXED_RATE, 0),
169 WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
170 WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
171 WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
172 WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
173 WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
174 WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
175 WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
176 WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
177 WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
178 WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
179 WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
180 WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
181 WCN36XX_CFG_VAL(STATS_PERIOD, 10),
182 WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
183 WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
184 WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
185 WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
186 WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
187 WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
188 WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
189 WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
190 WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
191 WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
192 };
193
194 static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
195 {
196 struct wcn36xx_hal_cfg *entry;
197 u32 *val;
198
199 if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
200 wcn36xx_err("Not enough room for TLV entry\n");
201 return -ENOMEM;
202 }
203
204 entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
205 entry->id = id;
206 entry->len = sizeof(u32);
207 entry->pad_bytes = 0;
208 entry->reserve = 0;
209
210 val = (u32 *) (entry + 1);
211 *val = value;
212
213 *len += sizeof(*entry) + sizeof(u32);
214
215 return 0;
216 }
217
218 static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
219 struct ieee80211_sta *sta,
220 struct wcn36xx_hal_config_bss_params *bss_params)
221 {
222 if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn))
223 bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
224 else if (sta && sta->ht_cap.ht_supported)
225 bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
226 else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f))
227 bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
228 else
229 bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
230 }
231
232 static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
233 {
234 return caps & flag ? 1 : 0;
235 }
236 static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
237 struct ieee80211_sta *sta,
238 struct wcn36xx_hal_config_bss_params *bss_params)
239 {
240 if (sta && sta->ht_cap.ht_supported) {
241 unsigned long caps = sta->ht_cap.cap;
242 bss_params->ht = sta->ht_cap.ht_supported;
243 bss_params->tx_channel_width_set = is_cap_supported(caps,
244 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
245 bss_params->lsig_tx_op_protection_full_support =
246 is_cap_supported(caps,
247 IEEE80211_HT_CAP_LSIG_TXOP_PROT);
248
249 bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
250 bss_params->lln_non_gf_coexist =
251 !!(vif->bss_conf.ht_operation_mode &
252 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
253 /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
254 bss_params->dual_cts_protection = 0;
255 /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
256 bss_params->ht20_coexist = 0;
257 }
258 }
259
260 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
261 struct wcn36xx_hal_config_sta_params *sta_params)
262 {
263 if (sta->ht_cap.ht_supported) {
264 unsigned long caps = sta->ht_cap.cap;
265 sta_params->ht_capable = sta->ht_cap.ht_supported;
266 sta_params->tx_channel_width_set = is_cap_supported(caps,
267 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
268 sta_params->lsig_txop_protection = is_cap_supported(caps,
269 IEEE80211_HT_CAP_LSIG_TXOP_PROT);
270
271 sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor;
272 sta_params->max_ampdu_density = sta->ht_cap.ampdu_density;
273 sta_params->max_amsdu_size = is_cap_supported(caps,
274 IEEE80211_HT_CAP_MAX_AMSDU);
275 sta_params->sgi_20Mhz = is_cap_supported(caps,
276 IEEE80211_HT_CAP_SGI_20);
277 sta_params->sgi_40mhz = is_cap_supported(caps,
278 IEEE80211_HT_CAP_SGI_40);
279 sta_params->green_field_capable = is_cap_supported(caps,
280 IEEE80211_HT_CAP_GRN_FLD);
281 sta_params->delayed_ba_support = is_cap_supported(caps,
282 IEEE80211_HT_CAP_DELAY_BA);
283 sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
284 IEEE80211_HT_CAP_DSSSCCK40);
285 }
286 }
287
288 static void wcn36xx_smd_set_sta_default_ht_params(
289 struct wcn36xx_hal_config_sta_params *sta_params)
290 {
291 sta_params->ht_capable = 1;
292 sta_params->tx_channel_width_set = 1;
293 sta_params->lsig_txop_protection = 1;
294 sta_params->max_ampdu_size = 3;
295 sta_params->max_ampdu_density = 5;
296 sta_params->max_amsdu_size = 0;
297 sta_params->sgi_20Mhz = 1;
298 sta_params->sgi_40mhz = 1;
299 sta_params->green_field_capable = 1;
300 sta_params->delayed_ba_support = 0;
301 sta_params->dsss_cck_mode_40mhz = 1;
302 }
303
304 static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
305 struct ieee80211_vif *vif,
306 struct ieee80211_sta *sta,
307 struct wcn36xx_hal_config_sta_params *sta_params)
308 {
309 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
310 struct wcn36xx_sta *priv_sta = NULL;
311 if (vif->type == NL80211_IFTYPE_ADHOC ||
312 vif->type == NL80211_IFTYPE_AP ||
313 vif->type == NL80211_IFTYPE_MESH_POINT) {
314 sta_params->type = 1;
315 sta_params->sta_index = 0xFF;
316 } else {
317 sta_params->type = 0;
318 sta_params->sta_index = 1;
319 }
320
321 sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
322
323 /*
324 * In STA mode ieee80211_sta contains bssid and ieee80211_vif
325 * contains our mac address. In AP mode we are bssid so vif
326 * contains bssid and ieee80211_sta contains mac.
327 */
328 if (NL80211_IFTYPE_STATION == vif->type)
329 memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
330 else
331 memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
332
333 sta_params->encrypt_type = priv_vif->encrypt_type;
334 sta_params->short_preamble_supported = true;
335
336 sta_params->rifs_mode = 0;
337 sta_params->rmf = 0;
338 sta_params->action = 0;
339 sta_params->uapsd = 0;
340 sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
341 sta_params->max_ampdu_duration = 0;
342 sta_params->bssid_index = priv_vif->bss_index;
343 sta_params->p2p = 0;
344
345 if (sta) {
346 priv_sta = (struct wcn36xx_sta *)sta->drv_priv;
347 if (NL80211_IFTYPE_STATION == vif->type)
348 memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
349 else
350 memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
351 sta_params->wmm_enabled = sta->wme;
352 sta_params->max_sp_len = sta->max_sp;
353 sta_params->aid = priv_sta->aid;
354 wcn36xx_smd_set_sta_ht_params(sta, sta_params);
355 memcpy(&sta_params->supported_rates, &priv_sta->supported_rates,
356 sizeof(priv_sta->supported_rates));
357 } else {
358 wcn36xx_set_default_rates(&sta_params->supported_rates);
359 wcn36xx_smd_set_sta_default_ht_params(sta_params);
360 }
361 }
362
363 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
364 {
365 int ret = 0;
366 unsigned long start;
367 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
368
369 init_completion(&wcn->hal_rsp_compl);
370 start = jiffies;
371 ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
372 if (ret) {
373 wcn36xx_err("HAL TX failed\n");
374 goto out;
375 }
376 if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
377 msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
378 wcn36xx_err("Timeout! No SMD response in %dms\n",
379 HAL_MSG_TIMEOUT);
380 ret = -ETIME;
381 goto out;
382 }
383 wcn36xx_dbg(WCN36XX_DBG_SMD, "SMD command completed in %dms",
384 jiffies_to_msecs(jiffies - start));
385 out:
386 return ret;
387 }
388
389 #define INIT_HAL_MSG(msg_body, type) \
390 do { \
391 memset(&msg_body, 0, sizeof(msg_body)); \
392 msg_body.header.msg_type = type; \
393 msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
394 msg_body.header.len = sizeof(msg_body); \
395 } while (0) \
396
397 #define PREPARE_HAL_BUF(send_buf, msg_body) \
398 do { \
399 memset(send_buf, 0, msg_body.header.len); \
400 memcpy(send_buf, &msg_body, sizeof(msg_body)); \
401 } while (0) \
402
403 static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
404 {
405 struct wcn36xx_fw_msg_status_rsp *rsp;
406
407 if (len < sizeof(struct wcn36xx_hal_msg_header) +
408 sizeof(struct wcn36xx_fw_msg_status_rsp))
409 return -EIO;
410
411 rsp = (struct wcn36xx_fw_msg_status_rsp *)
412 (buf + sizeof(struct wcn36xx_hal_msg_header));
413
414 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
415 return rsp->status;
416
417 return 0;
418 }
419
420 static int wcn36xx_smd_rsp_status_check_v2(struct wcn36xx *wcn, void *buf,
421 size_t len)
422 {
423 struct wcn36xx_fw_msg_status_rsp_v2 *rsp;
424
425 if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp))
426 return wcn36xx_smd_rsp_status_check(buf, len);
427
428 rsp = buf + sizeof(struct wcn36xx_hal_msg_header);
429
430 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
431 return rsp->status;
432
433 return 0;
434 }
435
436 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
437 {
438 struct nv_data *nv_d;
439 struct wcn36xx_hal_nv_img_download_req_msg msg_body;
440 int fw_bytes_left;
441 int ret;
442 u16 fm_offset = 0;
443
444 if (!wcn->nv) {
445 ret = request_firmware(&wcn->nv, WLAN_NV_FILE, wcn->dev);
446 if (ret) {
447 wcn36xx_err("Failed to load nv file %s: %d\n",
448 WLAN_NV_FILE, ret);
449 goto out;
450 }
451 }
452
453 nv_d = (struct nv_data *)wcn->nv->data;
454 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
455
456 msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
457
458 msg_body.frag_number = 0;
459 /* hal_buf must be protected with mutex */
460 mutex_lock(&wcn->hal_mutex);
461
462 do {
463 fw_bytes_left = wcn->nv->size - fm_offset - 4;
464 if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
465 msg_body.last_fragment = 0;
466 msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
467 } else {
468 msg_body.last_fragment = 1;
469 msg_body.nv_img_buffer_size = fw_bytes_left;
470
471 /* Do not forget update general message len */
472 msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
473
474 }
475
476 /* Add load NV request message header */
477 memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body));
478
479 /* Add NV body itself */
480 memcpy(wcn->hal_buf + sizeof(msg_body),
481 &nv_d->table + fm_offset,
482 msg_body.nv_img_buffer_size);
483
484 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
485 if (ret)
486 goto out_unlock;
487 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
488 wcn->hal_rsp_len);
489 if (ret) {
490 wcn36xx_err("hal_load_nv response failed err=%d\n",
491 ret);
492 goto out_unlock;
493 }
494 msg_body.frag_number++;
495 fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
496
497 } while (msg_body.last_fragment != 1);
498
499 out_unlock:
500 mutex_unlock(&wcn->hal_mutex);
501 out: return ret;
502 }
503
504 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
505 {
506 struct wcn36xx_hal_mac_start_rsp_msg *rsp;
507
508 if (len < sizeof(*rsp))
509 return -EIO;
510
511 rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf;
512
513 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
514 return -EIO;
515
516 memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
517 WCN36XX_HAL_VERSION_LENGTH);
518 memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
519 WCN36XX_HAL_VERSION_LENGTH);
520
521 /* null terminate the strings, just in case */
522 wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
523 wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
524
525 wcn->fw_revision = rsp->start_rsp_params.version.revision;
526 wcn->fw_version = rsp->start_rsp_params.version.version;
527 wcn->fw_minor = rsp->start_rsp_params.version.minor;
528 wcn->fw_major = rsp->start_rsp_params.version.major;
529
530 wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
531 wcn->wlan_version, wcn->crm_version);
532
533 wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
534 wcn->fw_major, wcn->fw_minor,
535 wcn->fw_version, wcn->fw_revision,
536 rsp->start_rsp_params.stations,
537 rsp->start_rsp_params.bssids);
538
539 return 0;
540 }
541
542 int wcn36xx_smd_start(struct wcn36xx *wcn)
543 {
544 struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
545 int ret = 0;
546 int i;
547 size_t len;
548
549 mutex_lock(&wcn->hal_mutex);
550 INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
551
552 msg_body.params.type = DRIVER_TYPE_PRODUCTION;
553 msg_body.params.len = 0;
554
555 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
556
557 body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
558 len = body->header.len;
559
560 for (i = 0; i < ARRAY_SIZE(wcn36xx_cfg_vals); i++) {
561 ret = put_cfg_tlv_u32(wcn, &len, wcn36xx_cfg_vals[i].cfg_id,
562 wcn36xx_cfg_vals[i].value);
563 if (ret)
564 goto out;
565 }
566 body->header.len = len;
567 body->params.len = len - sizeof(*body);
568
569 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
570 msg_body.params.type);
571
572 ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
573 if (ret) {
574 wcn36xx_err("Sending hal_start failed\n");
575 goto out;
576 }
577
578 ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
579 if (ret) {
580 wcn36xx_err("hal_start response failed err=%d\n", ret);
581 goto out;
582 }
583
584 out:
585 mutex_unlock(&wcn->hal_mutex);
586 return ret;
587 }
588
589 int wcn36xx_smd_stop(struct wcn36xx *wcn)
590 {
591 struct wcn36xx_hal_mac_stop_req_msg msg_body;
592 int ret = 0;
593
594 mutex_lock(&wcn->hal_mutex);
595 INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
596
597 msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
598
599 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
600
601 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
602 if (ret) {
603 wcn36xx_err("Sending hal_stop failed\n");
604 goto out;
605 }
606 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
607 if (ret) {
608 wcn36xx_err("hal_stop response failed err=%d\n", ret);
609 goto out;
610 }
611 out:
612 mutex_unlock(&wcn->hal_mutex);
613 return ret;
614 }
615
616 int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode)
617 {
618 struct wcn36xx_hal_init_scan_req_msg msg_body;
619 int ret = 0;
620
621 mutex_lock(&wcn->hal_mutex);
622 INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
623
624 msg_body.mode = mode;
625
626 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
627
628 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
629
630 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
631 if (ret) {
632 wcn36xx_err("Sending hal_init_scan failed\n");
633 goto out;
634 }
635 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
636 if (ret) {
637 wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
638 goto out;
639 }
640 out:
641 mutex_unlock(&wcn->hal_mutex);
642 return ret;
643 }
644
645 int wcn36xx_smd_start_scan(struct wcn36xx *wcn)
646 {
647 struct wcn36xx_hal_start_scan_req_msg msg_body;
648 int ret = 0;
649
650 mutex_lock(&wcn->hal_mutex);
651 INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
652
653 msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
654
655 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
656
657 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
658 msg_body.scan_channel);
659
660 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
661 if (ret) {
662 wcn36xx_err("Sending hal_start_scan failed\n");
663 goto out;
664 }
665 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
666 if (ret) {
667 wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
668 goto out;
669 }
670 out:
671 mutex_unlock(&wcn->hal_mutex);
672 return ret;
673 }
674
675 int wcn36xx_smd_end_scan(struct wcn36xx *wcn)
676 {
677 struct wcn36xx_hal_end_scan_req_msg msg_body;
678 int ret = 0;
679
680 mutex_lock(&wcn->hal_mutex);
681 INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
682
683 msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
684
685 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
686
687 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
688 msg_body.scan_channel);
689
690 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
691 if (ret) {
692 wcn36xx_err("Sending hal_end_scan failed\n");
693 goto out;
694 }
695 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
696 if (ret) {
697 wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
698 goto out;
699 }
700 out:
701 mutex_unlock(&wcn->hal_mutex);
702 return ret;
703 }
704
705 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
706 enum wcn36xx_hal_sys_mode mode)
707 {
708 struct wcn36xx_hal_finish_scan_req_msg msg_body;
709 int ret = 0;
710
711 mutex_lock(&wcn->hal_mutex);
712 INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
713
714 msg_body.mode = mode;
715
716 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
717
718 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
719 msg_body.mode);
720
721 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
722 if (ret) {
723 wcn36xx_err("Sending hal_finish_scan failed\n");
724 goto out;
725 }
726 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
727 if (ret) {
728 wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
729 goto out;
730 }
731 out:
732 mutex_unlock(&wcn->hal_mutex);
733 return ret;
734 }
735
736 static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
737 {
738 struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
739 int ret = 0;
740
741 ret = wcn36xx_smd_rsp_status_check(buf, len);
742 if (ret)
743 return ret;
744 rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf;
745 wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
746 rsp->channel_number, rsp->status);
747 return ret;
748 }
749
750 int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
751 struct ieee80211_vif *vif, int ch)
752 {
753 struct wcn36xx_hal_switch_channel_req_msg msg_body;
754 int ret = 0;
755
756 mutex_lock(&wcn->hal_mutex);
757 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
758
759 msg_body.channel_number = (u8)ch;
760 msg_body.tx_mgmt_power = 0xbf;
761 msg_body.max_tx_power = 0xbf;
762 memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
763
764 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
765
766 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
767 if (ret) {
768 wcn36xx_err("Sending hal_switch_channel failed\n");
769 goto out;
770 }
771 ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
772 if (ret) {
773 wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
774 goto out;
775 }
776 out:
777 mutex_unlock(&wcn->hal_mutex);
778 return ret;
779 }
780
781 static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
782 {
783 struct wcn36xx_hal_update_scan_params_resp *rsp;
784
785 rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf;
786
787 /* Remove the PNO version bit */
788 rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK));
789
790 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
791 wcn36xx_warn("error response from update scan\n");
792 return rsp->status;
793 }
794
795 return 0;
796 }
797
798 int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn)
799 {
800 struct wcn36xx_hal_update_scan_params_req msg_body;
801 int ret = 0;
802
803 mutex_lock(&wcn->hal_mutex);
804 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
805
806 msg_body.dot11d_enabled = 0;
807 msg_body.dot11d_resolved = 0;
808 msg_body.channel_count = 26;
809 msg_body.active_min_ch_time = 60;
810 msg_body.active_max_ch_time = 120;
811 msg_body.passive_min_ch_time = 60;
812 msg_body.passive_max_ch_time = 110;
813 msg_body.state = 0;
814
815 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
816
817 wcn36xx_dbg(WCN36XX_DBG_HAL,
818 "hal update scan params channel_count %d\n",
819 msg_body.channel_count);
820
821 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
822 if (ret) {
823 wcn36xx_err("Sending hal_update_scan_params failed\n");
824 goto out;
825 }
826 ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf,
827 wcn->hal_rsp_len);
828 if (ret) {
829 wcn36xx_err("hal_update_scan_params response failed err=%d\n",
830 ret);
831 goto out;
832 }
833 out:
834 mutex_unlock(&wcn->hal_mutex);
835 return ret;
836 }
837
838 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
839 struct ieee80211_vif *vif,
840 void *buf,
841 size_t len)
842 {
843 struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
844 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
845
846 if (len < sizeof(*rsp))
847 return -EINVAL;
848
849 rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf;
850
851 if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
852 wcn36xx_warn("hal add sta self failure: %d\n",
853 rsp->status);
854 return rsp->status;
855 }
856
857 wcn36xx_dbg(WCN36XX_DBG_HAL,
858 "hal add sta self status %d self_sta_index %d dpu_index %d\n",
859 rsp->status, rsp->self_sta_index, rsp->dpu_index);
860
861 priv_vif->self_sta_index = rsp->self_sta_index;
862 priv_vif->self_dpu_desc_index = rsp->dpu_index;
863
864 return 0;
865 }
866
867 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
868 {
869 struct wcn36xx_hal_add_sta_self_req msg_body;
870 int ret = 0;
871
872 mutex_lock(&wcn->hal_mutex);
873 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
874
875 memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
876
877 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
878
879 wcn36xx_dbg(WCN36XX_DBG_HAL,
880 "hal add sta self self_addr %pM status %d\n",
881 msg_body.self_addr, msg_body.status);
882
883 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
884 if (ret) {
885 wcn36xx_err("Sending hal_add_sta_self failed\n");
886 goto out;
887 }
888 ret = wcn36xx_smd_add_sta_self_rsp(wcn,
889 vif,
890 wcn->hal_buf,
891 wcn->hal_rsp_len);
892 if (ret) {
893 wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
894 goto out;
895 }
896 out:
897 mutex_unlock(&wcn->hal_mutex);
898 return ret;
899 }
900
901 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
902 {
903 struct wcn36xx_hal_del_sta_self_req_msg msg_body;
904 int ret = 0;
905
906 mutex_lock(&wcn->hal_mutex);
907 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
908
909 memcpy(&msg_body.self_addr, addr, ETH_ALEN);
910
911 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
912
913 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
914 if (ret) {
915 wcn36xx_err("Sending hal_delete_sta_self failed\n");
916 goto out;
917 }
918 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
919 if (ret) {
920 wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
921 ret);
922 goto out;
923 }
924 out:
925 mutex_unlock(&wcn->hal_mutex);
926 return ret;
927 }
928
929 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
930 {
931 struct wcn36xx_hal_delete_sta_req_msg msg_body;
932 int ret = 0;
933
934 mutex_lock(&wcn->hal_mutex);
935 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
936
937 msg_body.sta_index = sta_index;
938
939 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
940
941 wcn36xx_dbg(WCN36XX_DBG_HAL,
942 "hal delete sta sta_index %d\n",
943 msg_body.sta_index);
944
945 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
946 if (ret) {
947 wcn36xx_err("Sending hal_delete_sta failed\n");
948 goto out;
949 }
950 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
951 if (ret) {
952 wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
953 goto out;
954 }
955 out:
956 mutex_unlock(&wcn->hal_mutex);
957 return ret;
958 }
959
960 static int wcn36xx_smd_join_rsp(void *buf, size_t len)
961 {
962 struct wcn36xx_hal_join_rsp_msg *rsp;
963
964 if (wcn36xx_smd_rsp_status_check(buf, len))
965 return -EIO;
966
967 rsp = (struct wcn36xx_hal_join_rsp_msg *)buf;
968
969 wcn36xx_dbg(WCN36XX_DBG_HAL,
970 "hal rsp join status %d tx_mgmt_power %d\n",
971 rsp->status, rsp->tx_mgmt_power);
972
973 return 0;
974 }
975
976 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
977 {
978 struct wcn36xx_hal_join_req_msg msg_body;
979 int ret = 0;
980
981 mutex_lock(&wcn->hal_mutex);
982 INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
983
984 memcpy(&msg_body.bssid, bssid, ETH_ALEN);
985 memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
986 msg_body.channel = ch;
987
988 if (conf_is_ht40_minus(&wcn->hw->conf))
989 msg_body.secondary_channel_offset =
990 PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
991 else if (conf_is_ht40_plus(&wcn->hw->conf))
992 msg_body.secondary_channel_offset =
993 PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
994 else
995 msg_body.secondary_channel_offset =
996 PHY_SINGLE_CHANNEL_CENTERED;
997
998 msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
999
1000 msg_body.max_tx_power = 0xbf;
1001 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1002
1003 wcn36xx_dbg(WCN36XX_DBG_HAL,
1004 "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
1005 msg_body.bssid, msg_body.self_sta_mac_addr,
1006 msg_body.channel, msg_body.link_state);
1007
1008 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1009 if (ret) {
1010 wcn36xx_err("Sending hal_join failed\n");
1011 goto out;
1012 }
1013 ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1014 if (ret) {
1015 wcn36xx_err("hal_join response failed err=%d\n", ret);
1016 goto out;
1017 }
1018 out:
1019 mutex_unlock(&wcn->hal_mutex);
1020 return ret;
1021 }
1022
1023 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
1024 const u8 *sta_mac,
1025 enum wcn36xx_hal_link_state state)
1026 {
1027 struct wcn36xx_hal_set_link_state_req_msg msg_body;
1028 int ret = 0;
1029
1030 mutex_lock(&wcn->hal_mutex);
1031 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
1032
1033 memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1034 memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
1035 msg_body.state = state;
1036
1037 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1038
1039 wcn36xx_dbg(WCN36XX_DBG_HAL,
1040 "hal set link state bssid %pM self_mac_addr %pM state %d\n",
1041 msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
1042
1043 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1044 if (ret) {
1045 wcn36xx_err("Sending hal_set_link_st failed\n");
1046 goto out;
1047 }
1048 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1049 if (ret) {
1050 wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
1051 goto out;
1052 }
1053 out:
1054 mutex_unlock(&wcn->hal_mutex);
1055 return ret;
1056 }
1057
1058 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
1059 const struct wcn36xx_hal_config_sta_params *orig,
1060 struct wcn36xx_hal_config_sta_params_v1 *v1)
1061 {
1062 /* convert orig to v1 format */
1063 memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
1064 memcpy(&v1->mac, orig->mac, ETH_ALEN);
1065 v1->aid = orig->aid;
1066 v1->type = orig->type;
1067 v1->listen_interval = orig->listen_interval;
1068 v1->ht_capable = orig->ht_capable;
1069
1070 v1->max_ampdu_size = orig->max_ampdu_size;
1071 v1->max_ampdu_density = orig->max_ampdu_density;
1072 v1->sgi_40mhz = orig->sgi_40mhz;
1073 v1->sgi_20Mhz = orig->sgi_20Mhz;
1074
1075 memcpy(&v1->supported_rates, &orig->supported_rates,
1076 sizeof(orig->supported_rates));
1077 v1->sta_index = orig->sta_index;
1078 }
1079
1080 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
1081 struct ieee80211_sta *sta,
1082 void *buf,
1083 size_t len)
1084 {
1085 struct wcn36xx_hal_config_sta_rsp_msg *rsp;
1086 struct config_sta_rsp_params *params;
1087 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
1088
1089 if (len < sizeof(*rsp))
1090 return -EINVAL;
1091
1092 rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf;
1093 params = &rsp->params;
1094
1095 if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1096 wcn36xx_warn("hal config sta response failure: %d\n",
1097 params->status);
1098 return -EIO;
1099 }
1100
1101 sta_priv->sta_index = params->sta_index;
1102 sta_priv->dpu_desc_index = params->dpu_index;
1103 sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
1104
1105 wcn36xx_dbg(WCN36XX_DBG_HAL,
1106 "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
1107 params->status, params->sta_index, params->bssid_index,
1108 params->uc_ucast_sig, params->p2p);
1109
1110 return 0;
1111 }
1112
1113 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
1114 const struct wcn36xx_hal_config_sta_req_msg *orig)
1115 {
1116 struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
1117 struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params;
1118
1119 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1120
1121 wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params,
1122 &msg_body.sta_params);
1123
1124 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1125
1126 wcn36xx_dbg(WCN36XX_DBG_HAL,
1127 "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1128 sta->action, sta->sta_index, sta->bssid_index,
1129 sta->bssid, sta->type, sta->mac, sta->aid);
1130
1131 return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1132 }
1133
1134 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1135 struct ieee80211_sta *sta)
1136 {
1137 struct wcn36xx_hal_config_sta_req_msg msg;
1138 struct wcn36xx_hal_config_sta_params *sta_params;
1139 int ret = 0;
1140
1141 mutex_lock(&wcn->hal_mutex);
1142 INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
1143
1144 sta_params = &msg.sta_params;
1145
1146 wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1147
1148 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1149 ret = wcn36xx_smd_config_sta_v1(wcn, &msg);
1150 } else {
1151 PREPARE_HAL_BUF(wcn->hal_buf, msg);
1152
1153 wcn36xx_dbg(WCN36XX_DBG_HAL,
1154 "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1155 sta_params->action, sta_params->sta_index,
1156 sta_params->bssid_index, sta_params->bssid,
1157 sta_params->type, sta_params->mac, sta_params->aid);
1158
1159 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1160 }
1161 if (ret) {
1162 wcn36xx_err("Sending hal_config_sta failed\n");
1163 goto out;
1164 }
1165 ret = wcn36xx_smd_config_sta_rsp(wcn,
1166 sta,
1167 wcn->hal_buf,
1168 wcn->hal_rsp_len);
1169 if (ret) {
1170 wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
1171 goto out;
1172 }
1173 out:
1174 mutex_unlock(&wcn->hal_mutex);
1175 return ret;
1176 }
1177
1178 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1179 const struct wcn36xx_hal_config_bss_req_msg *orig)
1180 {
1181 struct wcn36xx_hal_config_bss_req_msg_v1 msg_body;
1182 struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params;
1183 struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta;
1184
1185 INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ);
1186
1187 /* convert orig to v1 */
1188 memcpy(&msg_body.bss_params.bssid,
1189 &orig->bss_params.bssid, ETH_ALEN);
1190 memcpy(&msg_body.bss_params.self_mac_addr,
1191 &orig->bss_params.self_mac_addr, ETH_ALEN);
1192
1193 msg_body.bss_params.bss_type = orig->bss_params.bss_type;
1194 msg_body.bss_params.oper_mode = orig->bss_params.oper_mode;
1195 msg_body.bss_params.nw_type = orig->bss_params.nw_type;
1196
1197 msg_body.bss_params.short_slot_time_supported =
1198 orig->bss_params.short_slot_time_supported;
1199 msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist;
1200 msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist;
1201 msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist;
1202 msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist;
1203 msg_body.bss_params.lln_non_gf_coexist =
1204 orig->bss_params.lln_non_gf_coexist;
1205
1206 msg_body.bss_params.lsig_tx_op_protection_full_support =
1207 orig->bss_params.lsig_tx_op_protection_full_support;
1208 msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode;
1209 msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval;
1210 msg_body.bss_params.dtim_period = orig->bss_params.dtim_period;
1211 msg_body.bss_params.tx_channel_width_set =
1212 orig->bss_params.tx_channel_width_set;
1213 msg_body.bss_params.oper_channel = orig->bss_params.oper_channel;
1214 msg_body.bss_params.ext_channel = orig->bss_params.ext_channel;
1215
1216 msg_body.bss_params.reserved = orig->bss_params.reserved;
1217
1218 memcpy(&msg_body.bss_params.ssid,
1219 &orig->bss_params.ssid,
1220 sizeof(orig->bss_params.ssid));
1221
1222 msg_body.bss_params.action = orig->bss_params.action;
1223 msg_body.bss_params.rateset = orig->bss_params.rateset;
1224 msg_body.bss_params.ht = orig->bss_params.ht;
1225 msg_body.bss_params.obss_prot_enabled =
1226 orig->bss_params.obss_prot_enabled;
1227 msg_body.bss_params.rmf = orig->bss_params.rmf;
1228 msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode;
1229 msg_body.bss_params.dual_cts_protection =
1230 orig->bss_params.dual_cts_protection;
1231
1232 msg_body.bss_params.max_probe_resp_retry_limit =
1233 orig->bss_params.max_probe_resp_retry_limit;
1234 msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid;
1235 msg_body.bss_params.proxy_probe_resp =
1236 orig->bss_params.proxy_probe_resp;
1237 msg_body.bss_params.edca_params_valid =
1238 orig->bss_params.edca_params_valid;
1239
1240 memcpy(&msg_body.bss_params.acbe,
1241 &orig->bss_params.acbe,
1242 sizeof(orig->bss_params.acbe));
1243 memcpy(&msg_body.bss_params.acbk,
1244 &orig->bss_params.acbk,
1245 sizeof(orig->bss_params.acbk));
1246 memcpy(&msg_body.bss_params.acvi,
1247 &orig->bss_params.acvi,
1248 sizeof(orig->bss_params.acvi));
1249 memcpy(&msg_body.bss_params.acvo,
1250 &orig->bss_params.acvo,
1251 sizeof(orig->bss_params.acvo));
1252
1253 msg_body.bss_params.ext_set_sta_key_param_valid =
1254 orig->bss_params.ext_set_sta_key_param_valid;
1255
1256 memcpy(&msg_body.bss_params.ext_set_sta_key_param,
1257 &orig->bss_params.ext_set_sta_key_param,
1258 sizeof(orig->bss_params.acvo));
1259
1260 msg_body.bss_params.wcn36xx_hal_persona =
1261 orig->bss_params.wcn36xx_hal_persona;
1262 msg_body.bss_params.spectrum_mgt_enable =
1263 orig->bss_params.spectrum_mgt_enable;
1264 msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power;
1265 msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power;
1266
1267 wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta,
1268 &msg_body.bss_params.sta);
1269
1270 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1271
1272 wcn36xx_dbg(WCN36XX_DBG_HAL,
1273 "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1274 bss->bssid, bss->self_mac_addr, bss->bss_type,
1275 bss->oper_mode, bss->nw_type);
1276
1277 wcn36xx_dbg(WCN36XX_DBG_HAL,
1278 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1279 sta->bssid, sta->action, sta->sta_index,
1280 sta->bssid_index, sta->aid, sta->type, sta->mac);
1281
1282 return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1283 }
1284
1285
1286 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1287 struct ieee80211_vif *vif,
1288 void *buf,
1289 size_t len)
1290 {
1291 struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1292 struct wcn36xx_hal_config_bss_rsp_params *params;
1293 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
1294
1295 if (len < sizeof(*rsp))
1296 return -EINVAL;
1297
1298 rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
1299 params = &rsp->bss_rsp_params;
1300
1301 if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1302 wcn36xx_warn("hal config bss response failure: %d\n",
1303 params->status);
1304 return -EIO;
1305 }
1306
1307 wcn36xx_dbg(WCN36XX_DBG_HAL,
1308 "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1309 " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1310 " power %d ucast_dpu_signature %d\n",
1311 params->status, params->bss_index, params->dpu_desc_index,
1312 params->bss_sta_index, params->bss_self_sta_index,
1313 params->bss_bcast_sta_idx, params->mac,
1314 params->tx_mgmt_power, params->ucast_dpu_signature);
1315
1316 priv_vif->bss_index = params->bss_index;
1317
1318 if (priv_vif->sta) {
1319 priv_vif->sta->bss_sta_index = params->bss_sta_index;
1320 priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index;
1321 }
1322
1323 priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature;
1324
1325 return 0;
1326 }
1327
1328 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1329 struct ieee80211_sta *sta, const u8 *bssid,
1330 bool update)
1331 {
1332 struct wcn36xx_hal_config_bss_req_msg msg;
1333 struct wcn36xx_hal_config_bss_params *bss;
1334 struct wcn36xx_hal_config_sta_params *sta_params;
1335 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1336 int ret = 0;
1337
1338 mutex_lock(&wcn->hal_mutex);
1339 INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ);
1340
1341 bss = &msg.bss_params;
1342 sta_params = &bss->sta;
1343
1344 WARN_ON(is_zero_ether_addr(bssid));
1345
1346 memcpy(&bss->bssid, bssid, ETH_ALEN);
1347
1348 memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1349
1350 if (vif->type == NL80211_IFTYPE_STATION) {
1351 bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1352
1353 /* STA */
1354 bss->oper_mode = 1;
1355 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1356 } else if (vif->type == NL80211_IFTYPE_AP ||
1357 vif->type == NL80211_IFTYPE_MESH_POINT) {
1358 bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1359
1360 /* AP */
1361 bss->oper_mode = 0;
1362 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1363 } else if (vif->type == NL80211_IFTYPE_ADHOC) {
1364 bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1365
1366 /* STA */
1367 bss->oper_mode = 1;
1368 } else {
1369 wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1370 }
1371
1372 if (vif->type == NL80211_IFTYPE_STATION)
1373 wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1374 else
1375 bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1376
1377 bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1378 bss->lla_coexist = 0;
1379 bss->llb_coexist = 0;
1380 bss->llg_coexist = 0;
1381 bss->rifs_mode = 0;
1382 bss->beacon_interval = vif->bss_conf.beacon_int;
1383 bss->dtim_period = vif_priv->dtim_period;
1384
1385 wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1386
1387 bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1388
1389 if (conf_is_ht40_minus(&wcn->hw->conf))
1390 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1391 else if (conf_is_ht40_plus(&wcn->hw->conf))
1392 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1393 else
1394 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1395
1396 bss->reserved = 0;
1397 wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1398
1399 /* wcn->ssid is only valid in AP and IBSS mode */
1400 bss->ssid.length = vif_priv->ssid.length;
1401 memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1402
1403 bss->obss_prot_enabled = 0;
1404 bss->rmf = 0;
1405 bss->max_probe_resp_retry_limit = 0;
1406 bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1407 bss->proxy_probe_resp = 0;
1408 bss->edca_params_valid = 0;
1409
1410 /* FIXME: set acbe, acbk, acvi and acvo */
1411
1412 bss->ext_set_sta_key_param_valid = 0;
1413
1414 /* FIXME: set ext_set_sta_key_param */
1415
1416 bss->spectrum_mgt_enable = 0;
1417 bss->tx_mgmt_power = 0;
1418 bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1419
1420 bss->action = update;
1421
1422 wcn36xx_dbg(WCN36XX_DBG_HAL,
1423 "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1424 bss->bssid, bss->self_mac_addr, bss->bss_type,
1425 bss->oper_mode, bss->nw_type);
1426
1427 wcn36xx_dbg(WCN36XX_DBG_HAL,
1428 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1429 sta_params->bssid, sta_params->action,
1430 sta_params->sta_index, sta_params->bssid_index,
1431 sta_params->aid, sta_params->type,
1432 sta_params->mac);
1433
1434 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1435 ret = wcn36xx_smd_config_bss_v1(wcn, &msg);
1436 } else {
1437 PREPARE_HAL_BUF(wcn->hal_buf, msg);
1438
1439 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1440 }
1441 if (ret) {
1442 wcn36xx_err("Sending hal_config_bss failed\n");
1443 goto out;
1444 }
1445 ret = wcn36xx_smd_config_bss_rsp(wcn,
1446 vif,
1447 wcn->hal_buf,
1448 wcn->hal_rsp_len);
1449 if (ret) {
1450 wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1451 goto out;
1452 }
1453 out:
1454 mutex_unlock(&wcn->hal_mutex);
1455 return ret;
1456 }
1457
1458 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1459 {
1460 struct wcn36xx_hal_delete_bss_req_msg msg_body;
1461 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
1462 int ret = 0;
1463
1464 mutex_lock(&wcn->hal_mutex);
1465 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1466
1467 msg_body.bss_index = priv_vif->bss_index;
1468
1469 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1470
1471 wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1472
1473 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1474 if (ret) {
1475 wcn36xx_err("Sending hal_delete_bss failed\n");
1476 goto out;
1477 }
1478 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1479 if (ret) {
1480 wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1481 goto out;
1482 }
1483 out:
1484 mutex_unlock(&wcn->hal_mutex);
1485 return ret;
1486 }
1487
1488 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1489 struct sk_buff *skb_beacon, u16 tim_off,
1490 u16 p2p_off)
1491 {
1492 struct wcn36xx_hal_send_beacon_req_msg msg_body;
1493 int ret = 0;
1494
1495 mutex_lock(&wcn->hal_mutex);
1496 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1497
1498 /* TODO need to find out why this is needed? */
1499 msg_body.beacon_length = skb_beacon->len + 6;
1500
1501 if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) {
1502 memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32));
1503 memcpy(&(msg_body.beacon[4]), skb_beacon->data,
1504 skb_beacon->len);
1505 } else {
1506 wcn36xx_err("Beacon is to big: beacon size=%d\n",
1507 msg_body.beacon_length);
1508 ret = -ENOMEM;
1509 goto out;
1510 }
1511 memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1512
1513 /* TODO need to find out why this is needed? */
1514 if (vif->type == NL80211_IFTYPE_MESH_POINT)
1515 /* mesh beacon don't need this, so push further down */
1516 msg_body.tim_ie_offset = 256;
1517 else
1518 msg_body.tim_ie_offset = tim_off+4;
1519 msg_body.p2p_ie_offset = p2p_off;
1520 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1521
1522 wcn36xx_dbg(WCN36XX_DBG_HAL,
1523 "hal send beacon beacon_length %d\n",
1524 msg_body.beacon_length);
1525
1526 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1527 if (ret) {
1528 wcn36xx_err("Sending hal_send_beacon failed\n");
1529 goto out;
1530 }
1531 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1532 if (ret) {
1533 wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
1534 goto out;
1535 }
1536 out:
1537 mutex_unlock(&wcn->hal_mutex);
1538 return ret;
1539 }
1540
1541 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
1542 struct ieee80211_vif *vif,
1543 struct sk_buff *skb)
1544 {
1545 struct wcn36xx_hal_send_probe_resp_req_msg msg;
1546 int ret = 0;
1547
1548 mutex_lock(&wcn->hal_mutex);
1549 INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
1550
1551 if (skb->len > BEACON_TEMPLATE_SIZE) {
1552 wcn36xx_warn("probe response template is too big: %d\n",
1553 skb->len);
1554 ret = -E2BIG;
1555 goto out;
1556 }
1557
1558 msg.probe_resp_template_len = skb->len;
1559 memcpy(&msg.probe_resp_template, skb->data, skb->len);
1560
1561 memcpy(msg.bssid, vif->addr, ETH_ALEN);
1562
1563 PREPARE_HAL_BUF(wcn->hal_buf, msg);
1564
1565 wcn36xx_dbg(WCN36XX_DBG_HAL,
1566 "hal update probe rsp len %d bssid %pM\n",
1567 msg.probe_resp_template_len, msg.bssid);
1568
1569 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1570 if (ret) {
1571 wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
1572 goto out;
1573 }
1574 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1575 if (ret) {
1576 wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
1577 ret);
1578 goto out;
1579 }
1580 out:
1581 mutex_unlock(&wcn->hal_mutex);
1582 return ret;
1583 }
1584
1585 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
1586 enum ani_ed_type enc_type,
1587 u8 keyidx,
1588 u8 keylen,
1589 u8 *key,
1590 u8 sta_index)
1591 {
1592 struct wcn36xx_hal_set_sta_key_req_msg msg_body;
1593 int ret = 0;
1594
1595 mutex_lock(&wcn->hal_mutex);
1596 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
1597
1598 msg_body.set_sta_key_params.sta_index = sta_index;
1599 msg_body.set_sta_key_params.enc_type = enc_type;
1600
1601 msg_body.set_sta_key_params.key[0].id = keyidx;
1602 msg_body.set_sta_key_params.key[0].unicast = 1;
1603 msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
1604 msg_body.set_sta_key_params.key[0].pae_role = 0;
1605 msg_body.set_sta_key_params.key[0].length = keylen;
1606 memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
1607 msg_body.set_sta_key_params.single_tid_rc = 1;
1608
1609 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1610
1611 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1612 if (ret) {
1613 wcn36xx_err("Sending hal_set_stakey failed\n");
1614 goto out;
1615 }
1616 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1617 if (ret) {
1618 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
1619 goto out;
1620 }
1621 out:
1622 mutex_unlock(&wcn->hal_mutex);
1623 return ret;
1624 }
1625
1626 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
1627 enum ani_ed_type enc_type,
1628 u8 keyidx,
1629 u8 keylen,
1630 u8 *key)
1631 {
1632 struct wcn36xx_hal_set_bss_key_req_msg msg_body;
1633 int ret = 0;
1634
1635 mutex_lock(&wcn->hal_mutex);
1636 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
1637 msg_body.bss_idx = 0;
1638 msg_body.enc_type = enc_type;
1639 msg_body.num_keys = 1;
1640 msg_body.keys[0].id = keyidx;
1641 msg_body.keys[0].unicast = 0;
1642 msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
1643 msg_body.keys[0].pae_role = 0;
1644 msg_body.keys[0].length = keylen;
1645 memcpy(msg_body.keys[0].key, key, keylen);
1646
1647 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1648
1649 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1650 if (ret) {
1651 wcn36xx_err("Sending hal_set_bsskey failed\n");
1652 goto out;
1653 }
1654 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1655 if (ret) {
1656 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
1657 goto out;
1658 }
1659 out:
1660 mutex_unlock(&wcn->hal_mutex);
1661 return ret;
1662 }
1663
1664 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
1665 enum ani_ed_type enc_type,
1666 u8 keyidx,
1667 u8 sta_index)
1668 {
1669 struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
1670 int ret = 0;
1671
1672 mutex_lock(&wcn->hal_mutex);
1673 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
1674
1675 msg_body.sta_idx = sta_index;
1676 msg_body.enc_type = enc_type;
1677 msg_body.key_id = keyidx;
1678
1679 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1680
1681 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1682 if (ret) {
1683 wcn36xx_err("Sending hal_remove_stakey failed\n");
1684 goto out;
1685 }
1686 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1687 if (ret) {
1688 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
1689 goto out;
1690 }
1691 out:
1692 mutex_unlock(&wcn->hal_mutex);
1693 return ret;
1694 }
1695
1696 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
1697 enum ani_ed_type enc_type,
1698 u8 keyidx)
1699 {
1700 struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
1701 int ret = 0;
1702
1703 mutex_lock(&wcn->hal_mutex);
1704 INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
1705 msg_body.bss_idx = 0;
1706 msg_body.enc_type = enc_type;
1707 msg_body.key_id = keyidx;
1708
1709 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1710
1711 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1712 if (ret) {
1713 wcn36xx_err("Sending hal_remove_bsskey failed\n");
1714 goto out;
1715 }
1716 ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
1717 wcn->hal_rsp_len);
1718 if (ret) {
1719 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
1720 goto out;
1721 }
1722 out:
1723 mutex_unlock(&wcn->hal_mutex);
1724 return ret;
1725 }
1726
1727 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1728 {
1729 struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1730 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1731 int ret = 0;
1732
1733 mutex_lock(&wcn->hal_mutex);
1734 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
1735
1736 msg_body.bss_index = vif_priv->bss_index;
1737 msg_body.tbtt = vif->bss_conf.sync_tsf;
1738 msg_body.dtim_period = vif_priv->dtim_period;
1739
1740 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1741
1742 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1743 if (ret) {
1744 wcn36xx_err("Sending hal_enter_bmps failed\n");
1745 goto out;
1746 }
1747 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1748 if (ret) {
1749 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
1750 goto out;
1751 }
1752 out:
1753 mutex_unlock(&wcn->hal_mutex);
1754 return ret;
1755 }
1756
1757 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1758 {
1759 struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1760 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1761 int ret = 0;
1762
1763 mutex_lock(&wcn->hal_mutex);
1764 INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
1765
1766 msg_body.bss_index = vif_priv->bss_index;
1767
1768 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1769
1770 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1771 if (ret) {
1772 wcn36xx_err("Sending hal_exit_bmps failed\n");
1773 goto out;
1774 }
1775 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1776 if (ret) {
1777 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
1778 goto out;
1779 }
1780 out:
1781 mutex_unlock(&wcn->hal_mutex);
1782 return ret;
1783 }
1784 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
1785 {
1786 struct wcn36xx_hal_set_power_params_req_msg msg_body;
1787 int ret = 0;
1788
1789 mutex_lock(&wcn->hal_mutex);
1790 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
1791
1792 /*
1793 * When host is down ignore every second dtim
1794 */
1795 if (ignore_dtim) {
1796 msg_body.ignore_dtim = 1;
1797 msg_body.dtim_period = 2;
1798 }
1799 msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
1800
1801 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1802
1803 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1804 if (ret) {
1805 wcn36xx_err("Sending hal_set_power_params failed\n");
1806 goto out;
1807 }
1808
1809 out:
1810 mutex_unlock(&wcn->hal_mutex);
1811 return ret;
1812 }
1813 /* Notice: This function should be called after associated, or else it
1814 * will be invalid
1815 */
1816 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
1817 struct ieee80211_vif *vif,
1818 int packet_type)
1819 {
1820 struct wcn36xx_hal_keep_alive_req_msg msg_body;
1821 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1822 int ret = 0;
1823
1824 mutex_lock(&wcn->hal_mutex);
1825 INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
1826
1827 if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
1828 msg_body.bss_index = vif_priv->bss_index;
1829 msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
1830 msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
1831 } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
1832 /* TODO: it also support ARP response type */
1833 } else {
1834 wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
1835 ret = -EINVAL;
1836 goto out;
1837 }
1838
1839 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1840
1841 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1842 if (ret) {
1843 wcn36xx_err("Sending hal_keep_alive failed\n");
1844 goto out;
1845 }
1846 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1847 if (ret) {
1848 wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
1849 goto out;
1850 }
1851 out:
1852 mutex_unlock(&wcn->hal_mutex);
1853 return ret;
1854 }
1855
1856 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
1857 u32 arg3, u32 arg4, u32 arg5)
1858 {
1859 struct wcn36xx_hal_dump_cmd_req_msg msg_body;
1860 int ret = 0;
1861
1862 mutex_lock(&wcn->hal_mutex);
1863 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
1864
1865 msg_body.arg1 = arg1;
1866 msg_body.arg2 = arg2;
1867 msg_body.arg3 = arg3;
1868 msg_body.arg4 = arg4;
1869 msg_body.arg5 = arg5;
1870
1871 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1872
1873 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1874 if (ret) {
1875 wcn36xx_err("Sending hal_dump_cmd failed\n");
1876 goto out;
1877 }
1878 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1879 if (ret) {
1880 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
1881 goto out;
1882 }
1883 out:
1884 mutex_unlock(&wcn->hal_mutex);
1885 return ret;
1886 }
1887
1888 void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
1889 {
1890 int arr_idx, bit_idx;
1891
1892 if (cap < 0 || cap > 127) {
1893 wcn36xx_warn("error cap idx %d\n", cap);
1894 return;
1895 }
1896
1897 arr_idx = cap / 32;
1898 bit_idx = cap % 32;
1899 bitmap[arr_idx] |= (1 << bit_idx);
1900 }
1901
1902 int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
1903 {
1904 int arr_idx, bit_idx;
1905 int ret = 0;
1906
1907 if (cap < 0 || cap > 127) {
1908 wcn36xx_warn("error cap idx %d\n", cap);
1909 return -EINVAL;
1910 }
1911
1912 arr_idx = cap / 32;
1913 bit_idx = cap % 32;
1914 ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0;
1915 return ret;
1916 }
1917
1918 void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
1919 {
1920 int arr_idx, bit_idx;
1921
1922 if (cap < 0 || cap > 127) {
1923 wcn36xx_warn("error cap idx %d\n", cap);
1924 return;
1925 }
1926
1927 arr_idx = cap / 32;
1928 bit_idx = cap % 32;
1929 bitmap[arr_idx] &= ~(1 << bit_idx);
1930 }
1931
1932 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
1933 {
1934 struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
1935 int ret = 0, i;
1936
1937 mutex_lock(&wcn->hal_mutex);
1938 INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
1939
1940 set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
1941
1942 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1943
1944 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1945 if (ret) {
1946 wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
1947 goto out;
1948 }
1949 if (wcn->hal_rsp_len != sizeof(*rsp)) {
1950 wcn36xx_err("Invalid hal_feature_caps_exchange response");
1951 goto out;
1952 }
1953
1954 rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
1955
1956 for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
1957 wcn->fw_feat_caps[i] = rsp->feat_caps[i];
1958 out:
1959 mutex_unlock(&wcn->hal_mutex);
1960 return ret;
1961 }
1962
1963 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
1964 struct ieee80211_sta *sta,
1965 u16 tid,
1966 u16 *ssn,
1967 u8 direction,
1968 u8 sta_index)
1969 {
1970 struct wcn36xx_hal_add_ba_session_req_msg msg_body;
1971 int ret = 0;
1972
1973 mutex_lock(&wcn->hal_mutex);
1974 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
1975
1976 msg_body.sta_index = sta_index;
1977 memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
1978 msg_body.dialog_token = 0x10;
1979 msg_body.tid = tid;
1980
1981 /* Immediate BA because Delayed BA is not supported */
1982 msg_body.policy = 1;
1983 msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
1984 msg_body.timeout = 0;
1985 if (ssn)
1986 msg_body.ssn = *ssn;
1987 msg_body.direction = direction;
1988
1989 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1990
1991 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1992 if (ret) {
1993 wcn36xx_err("Sending hal_add_ba_session failed\n");
1994 goto out;
1995 }
1996 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1997 if (ret) {
1998 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
1999 goto out;
2000 }
2001 out:
2002 mutex_unlock(&wcn->hal_mutex);
2003 return ret;
2004 }
2005
2006 int wcn36xx_smd_add_ba(struct wcn36xx *wcn)
2007 {
2008 struct wcn36xx_hal_add_ba_req_msg msg_body;
2009 int ret = 0;
2010
2011 mutex_lock(&wcn->hal_mutex);
2012 INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
2013
2014 msg_body.session_id = 0;
2015 msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
2016
2017 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2018
2019 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2020 if (ret) {
2021 wcn36xx_err("Sending hal_add_ba failed\n");
2022 goto out;
2023 }
2024 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2025 if (ret) {
2026 wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
2027 goto out;
2028 }
2029 out:
2030 mutex_unlock(&wcn->hal_mutex);
2031 return ret;
2032 }
2033
2034 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index)
2035 {
2036 struct wcn36xx_hal_del_ba_req_msg msg_body;
2037 int ret = 0;
2038
2039 mutex_lock(&wcn->hal_mutex);
2040 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
2041
2042 msg_body.sta_index = sta_index;
2043 msg_body.tid = tid;
2044 msg_body.direction = 0;
2045 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2046
2047 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2048 if (ret) {
2049 wcn36xx_err("Sending hal_del_ba failed\n");
2050 goto out;
2051 }
2052 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2053 if (ret) {
2054 wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
2055 goto out;
2056 }
2057 out:
2058 mutex_unlock(&wcn->hal_mutex);
2059 return ret;
2060 }
2061
2062 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
2063 {
2064 struct wcn36xx_hal_trigger_ba_req_msg msg_body;
2065 struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
2066 int ret = 0;
2067
2068 mutex_lock(&wcn->hal_mutex);
2069 INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
2070
2071 msg_body.session_id = 0;
2072 msg_body.candidate_cnt = 1;
2073 msg_body.header.len += sizeof(*candidate);
2074 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2075
2076 candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
2077 (wcn->hal_buf + sizeof(msg_body));
2078 candidate->sta_index = sta_index;
2079 candidate->tid_bitmap = 1;
2080
2081 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2082 if (ret) {
2083 wcn36xx_err("Sending hal_trigger_ba failed\n");
2084 goto out;
2085 }
2086 ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
2087 wcn->hal_rsp_len);
2088 if (ret) {
2089 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
2090 goto out;
2091 }
2092 out:
2093 mutex_unlock(&wcn->hal_mutex);
2094 return ret;
2095 }
2096
2097 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
2098 {
2099 struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
2100
2101 if (len != sizeof(*rsp)) {
2102 wcn36xx_warn("Bad TX complete indication\n");
2103 return -EIO;
2104 }
2105
2106 wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
2107
2108 return 0;
2109 }
2110
2111 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2112 void *buf,
2113 size_t len)
2114 {
2115 struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
2116 struct ieee80211_vif *vif = NULL;
2117 struct wcn36xx_vif *tmp;
2118
2119 /* Old FW does not have bss index */
2120 if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
2121 list_for_each_entry(tmp, &wcn->vif_list, list) {
2122 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2123 tmp->bss_index);
2124 vif = container_of((void *)tmp,
2125 struct ieee80211_vif,
2126 drv_priv);
2127 ieee80211_connection_loss(vif);
2128 }
2129 return 0;
2130 }
2131
2132 if (len != sizeof(*rsp)) {
2133 wcn36xx_warn("Corrupted missed beacon indication\n");
2134 return -EIO;
2135 }
2136
2137 list_for_each_entry(tmp, &wcn->vif_list, list) {
2138 if (tmp->bss_index == rsp->bss_index) {
2139 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2140 rsp->bss_index);
2141 vif = container_of((void *)tmp,
2142 struct ieee80211_vif,
2143 drv_priv);
2144 ieee80211_connection_loss(vif);
2145 return 0;
2146 }
2147 }
2148
2149 wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
2150 return -ENOENT;
2151 }
2152
2153 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2154 void *buf,
2155 size_t len)
2156 {
2157 struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2158 struct wcn36xx_vif *tmp;
2159 struct ieee80211_sta *sta = NULL;
2160
2161 if (len != sizeof(*rsp)) {
2162 wcn36xx_warn("Corrupted delete sta indication\n");
2163 return -EIO;
2164 }
2165
2166 list_for_each_entry(tmp, &wcn->vif_list, list) {
2167 if (sta && (tmp->sta->sta_index == rsp->sta_id)) {
2168 sta = container_of((void *)tmp->sta,
2169 struct ieee80211_sta,
2170 drv_priv);
2171 wcn36xx_dbg(WCN36XX_DBG_HAL,
2172 "delete station indication %pM index %d\n",
2173 rsp->addr2,
2174 rsp->sta_id);
2175 ieee80211_report_low_ack(sta, 0);
2176 return 0;
2177 }
2178 }
2179
2180 wcn36xx_warn("STA with addr %pM and index %d not found\n",
2181 rsp->addr2,
2182 rsp->sta_id);
2183 return -ENOENT;
2184 }
2185
2186 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
2187 {
2188 struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
2189 size_t len;
2190 int ret = 0;
2191
2192 mutex_lock(&wcn->hal_mutex);
2193 INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
2194
2195 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2196
2197 body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
2198 len = msg_body.header.len;
2199
2200 put_cfg_tlv_u32(wcn, &len, cfg_id, value);
2201 body->header.len = len;
2202 body->len = len - sizeof(*body);
2203
2204 ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
2205 if (ret) {
2206 wcn36xx_err("Sending hal_update_cfg failed\n");
2207 goto out;
2208 }
2209 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2210 if (ret) {
2211 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
2212 goto out;
2213 }
2214 out:
2215 mutex_unlock(&wcn->hal_mutex);
2216 return ret;
2217 }
2218 static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
2219 {
2220 struct wcn36xx_hal_msg_header *msg_header = buf;
2221 struct wcn36xx_hal_ind_msg *msg_ind;
2222 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
2223
2224 switch (msg_header->msg_type) {
2225 case WCN36XX_HAL_START_RSP:
2226 case WCN36XX_HAL_CONFIG_STA_RSP:
2227 case WCN36XX_HAL_CONFIG_BSS_RSP:
2228 case WCN36XX_HAL_ADD_STA_SELF_RSP:
2229 case WCN36XX_HAL_STOP_RSP:
2230 case WCN36XX_HAL_DEL_STA_SELF_RSP:
2231 case WCN36XX_HAL_DELETE_STA_RSP:
2232 case WCN36XX_HAL_INIT_SCAN_RSP:
2233 case WCN36XX_HAL_START_SCAN_RSP:
2234 case WCN36XX_HAL_END_SCAN_RSP:
2235 case WCN36XX_HAL_FINISH_SCAN_RSP:
2236 case WCN36XX_HAL_DOWNLOAD_NV_RSP:
2237 case WCN36XX_HAL_DELETE_BSS_RSP:
2238 case WCN36XX_HAL_SEND_BEACON_RSP:
2239 case WCN36XX_HAL_SET_LINK_ST_RSP:
2240 case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
2241 case WCN36XX_HAL_SET_BSSKEY_RSP:
2242 case WCN36XX_HAL_SET_STAKEY_RSP:
2243 case WCN36XX_HAL_RMV_STAKEY_RSP:
2244 case WCN36XX_HAL_RMV_BSSKEY_RSP:
2245 case WCN36XX_HAL_ENTER_BMPS_RSP:
2246 case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
2247 case WCN36XX_HAL_EXIT_BMPS_RSP:
2248 case WCN36XX_HAL_KEEP_ALIVE_RSP:
2249 case WCN36XX_HAL_DUMP_COMMAND_RSP:
2250 case WCN36XX_HAL_ADD_BA_SESSION_RSP:
2251 case WCN36XX_HAL_ADD_BA_RSP:
2252 case WCN36XX_HAL_DEL_BA_RSP:
2253 case WCN36XX_HAL_TRIGGER_BA_RSP:
2254 case WCN36XX_HAL_UPDATE_CFG_RSP:
2255 case WCN36XX_HAL_JOIN_RSP:
2256 case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
2257 case WCN36XX_HAL_CH_SWITCH_RSP:
2258 case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
2259 memcpy(wcn->hal_buf, buf, len);
2260 wcn->hal_rsp_len = len;
2261 complete(&wcn->hal_rsp_compl);
2262 break;
2263
2264 case WCN36XX_HAL_COEX_IND:
2265 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
2266 case WCN36XX_HAL_OTA_TX_COMPL_IND:
2267 case WCN36XX_HAL_MISSED_BEACON_IND:
2268 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2269 msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
2270 if (!msg_ind)
2271 goto nomem;
2272 msg_ind->msg_len = len;
2273 msg_ind->msg = kmemdup(buf, len, GFP_KERNEL);
2274 if (!msg_ind->msg) {
2275 kfree(msg_ind);
2276 nomem:
2277 /*
2278 * FIXME: Do something smarter then just
2279 * printing an error.
2280 */
2281 wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
2282 msg_header->msg_type);
2283 break;
2284 }
2285 mutex_lock(&wcn->hal_ind_mutex);
2286 list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
2287 queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
2288 mutex_unlock(&wcn->hal_ind_mutex);
2289 wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
2290 break;
2291 default:
2292 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2293 msg_header->msg_type);
2294 }
2295 }
2296 static void wcn36xx_ind_smd_work(struct work_struct *work)
2297 {
2298 struct wcn36xx *wcn =
2299 container_of(work, struct wcn36xx, hal_ind_work);
2300 struct wcn36xx_hal_msg_header *msg_header;
2301 struct wcn36xx_hal_ind_msg *hal_ind_msg;
2302
2303 mutex_lock(&wcn->hal_ind_mutex);
2304
2305 hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
2306 struct wcn36xx_hal_ind_msg,
2307 list);
2308
2309 msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
2310
2311 switch (msg_header->msg_type) {
2312 case WCN36XX_HAL_COEX_IND:
2313 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
2314 break;
2315 case WCN36XX_HAL_OTA_TX_COMPL_IND:
2316 wcn36xx_smd_tx_compl_ind(wcn,
2317 hal_ind_msg->msg,
2318 hal_ind_msg->msg_len);
2319 break;
2320 case WCN36XX_HAL_MISSED_BEACON_IND:
2321 wcn36xx_smd_missed_beacon_ind(wcn,
2322 hal_ind_msg->msg,
2323 hal_ind_msg->msg_len);
2324 break;
2325 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2326 wcn36xx_smd_delete_sta_context_ind(wcn,
2327 hal_ind_msg->msg,
2328 hal_ind_msg->msg_len);
2329 break;
2330 default:
2331 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2332 msg_header->msg_type);
2333 }
2334 list_del(wcn->hal_ind_queue.next);
2335 kfree(hal_ind_msg->msg);
2336 kfree(hal_ind_msg);
2337 mutex_unlock(&wcn->hal_ind_mutex);
2338 }
2339 int wcn36xx_smd_open(struct wcn36xx *wcn)
2340 {
2341 int ret = 0;
2342 wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
2343 if (!wcn->hal_ind_wq) {
2344 wcn36xx_err("failed to allocate wq\n");
2345 ret = -ENOMEM;
2346 goto out;
2347 }
2348 INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
2349 INIT_LIST_HEAD(&wcn->hal_ind_queue);
2350 mutex_init(&wcn->hal_ind_mutex);
2351
2352 ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
2353 if (ret) {
2354 wcn36xx_err("failed to open control channel\n");
2355 goto free_wq;
2356 }
2357
2358 return ret;
2359
2360 free_wq:
2361 destroy_workqueue(wcn->hal_ind_wq);
2362 out:
2363 return ret;
2364 }
2365
2366 void wcn36xx_smd_close(struct wcn36xx *wcn)
2367 {
2368 wcn->ctrl_ops->close();
2369 destroy_workqueue(wcn->hal_ind_wq);
2370 mutex_destroy(&wcn->hal_ind_mutex);
2371 }
2372
2373 #line 115 "/work/ldvuser/andrianov/work/current--X--drivers/net/wireless/ath/wcn36xx/--X--defaultlinux-4.5-rc7--X--races--X--cpachecker/linux-4.5-rc7/csd_deg_dscv/19/dscv_tempdir/dscv/ri/races/drivers/net/wireless/ath/wcn36xx/smd.o.c.prepared" 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 "txrx.h"
20
21 static inline int get_rssi0(struct wcn36xx_rx_bd *bd)
22 {
23 return 100 - ((bd->phy_stat0 >> 24) & 0xff);
24 }
25
26 int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
27 {
28 struct ieee80211_rx_status status;
29 struct ieee80211_hdr *hdr;
30 struct wcn36xx_rx_bd *bd;
31 u16 fc, sn;
32
33 /*
34 * All fields must be 0, otherwise it can lead to
35 * unexpected consequences.
36 */
37 memset(&status, 0, sizeof(status));
38
39 bd = (struct wcn36xx_rx_bd *)skb->data;
40 buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
41 wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP,
42 "BD <<< ", (char *)bd,
43 sizeof(struct wcn36xx_rx_bd));
44
45 skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len);
46 skb_pull(skb, bd->pdu.mpdu_header_off);
47
48 status.mactime = 10;
49 status.freq = WCN36XX_CENTER_FREQ(wcn);
50 status.band = WCN36XX_BAND(wcn);
51 status.signal = -get_rssi0(bd);
52 status.antenna = 1;
53 status.rate_idx = 1;
54 status.flag = 0;
55 status.rx_flags = 0;
56 status.flag |= RX_FLAG_IV_STRIPPED |
57 RX_FLAG_MMIC_STRIPPED |
58 RX_FLAG_DECRYPTED;
59
60 wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag);
61
62 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
63
64 hdr = (struct ieee80211_hdr *) skb->data;
65 fc = __le16_to_cpu(hdr->frame_control);
66 sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
67
68 if (ieee80211_is_beacon(hdr->frame_control)) {
69 wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n",
70 skb, skb->len, fc, sn);
71 wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ",
72 (char *)skb->data, skb->len);
73 } else {
74 wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d\n",
75 skb, skb->len, fc, sn);
76 wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ",
77 (char *)skb->data, skb->len);
78 }
79
80 ieee80211_rx_irqsafe(wcn->hw, skb);
81
82 return 0;
83 }
84
85 static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd,
86 u32 mpdu_header_len,
87 u32 len,
88 u16 tid)
89 {
90 bd->pdu.mpdu_header_len = mpdu_header_len;
91 bd->pdu.mpdu_header_off = sizeof(*bd);
92 bd->pdu.mpdu_data_off = bd->pdu.mpdu_header_len +
93 bd->pdu.mpdu_header_off;
94 bd->pdu.mpdu_len = len;
95 bd->pdu.tid = tid;
96 bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS;
97 }
98
99 static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
100 u8 *addr)
101 {
102 struct wcn36xx_vif *vif_priv = NULL;
103 struct ieee80211_vif *vif = NULL;
104 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
105 vif = container_of((void *)vif_priv,
106 struct ieee80211_vif,
107 drv_priv);
108 if (memcmp(vif->addr, addr, ETH_ALEN) == 0)
109 return vif_priv;
110 }
111 wcn36xx_warn("vif %pM not found\n", addr);
112 return NULL;
113 }
114
115 static void wcn36xx_tx_start_ampdu(struct wcn36xx *wcn,
116 struct wcn36xx_sta *sta_priv,
117 struct sk_buff *skb)
118 {
119 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
120 struct ieee80211_sta *sta;
121 u8 *qc, tid;
122
123 if (!conf_is_ht(&wcn->hw->conf))
124 return;
125
126 sta = wcn36xx_priv_to_sta(sta_priv);
127
128 if (WARN_ON(!ieee80211_is_data_qos(hdr->frame_control)))
129 return;
130
131 if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
132 return;
133
134 qc = ieee80211_get_qos_ctl(hdr);
135 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
136
137 spin_lock(&sta_priv->ampdu_lock);
138 if (sta_priv->ampdu_state[tid] != WCN36XX_AMPDU_NONE)
139 goto out_unlock;
140
141 if (sta_priv->non_agg_frame_ct++ >= WCN36XX_AMPDU_START_THRESH) {
142 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
143 sta_priv->non_agg_frame_ct = 0;
144 ieee80211_start_tx_ba_session(sta, tid, 0);
145 }
146 out_unlock:
147 spin_unlock(&sta_priv->ampdu_lock);
148 }
149
150 static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
151 struct wcn36xx *wcn,
152 struct wcn36xx_vif **vif_priv,
153 struct wcn36xx_sta *sta_priv,
154 struct sk_buff *skb,
155 bool bcast)
156 {
157 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
158 struct ieee80211_vif *vif = NULL;
159 struct wcn36xx_vif *__vif_priv = NULL;
160 bool is_data_qos;
161
162 bd->bd_rate = WCN36XX_BD_RATE_DATA;
163
164 /*
165 * For not unicast frames mac80211 will not set sta pointer so use
166 * self_sta_index instead.
167 */
168 if (sta_priv) {
169 __vif_priv = sta_priv->vif;
170 vif = container_of((void *)__vif_priv,
171 struct ieee80211_vif,
172 drv_priv);
173
174 bd->dpu_sign = sta_priv->ucast_dpu_sign;
175 if (vif->type == NL80211_IFTYPE_STATION) {
176 bd->sta_index = sta_priv->bss_sta_index;
177 bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index;
178 } else if (vif->type == NL80211_IFTYPE_AP ||
179 vif->type == NL80211_IFTYPE_ADHOC ||
180 vif->type == NL80211_IFTYPE_MESH_POINT) {
181 bd->sta_index = sta_priv->sta_index;
182 bd->dpu_desc_idx = sta_priv->dpu_desc_index;
183 }
184 } else {
185 __vif_priv = get_vif_by_addr(wcn, hdr->addr2);
186 bd->sta_index = __vif_priv->self_sta_index;
187 bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
188 bd->dpu_sign = __vif_priv->self_ucast_dpu_sign;
189 }
190
191 if (ieee80211_is_nullfunc(hdr->frame_control) ||
192 (sta_priv && !sta_priv->is_data_encrypted))
193 bd->dpu_ne = 1;
194
195 if (bcast) {
196 bd->ub = 1;
197 bd->ack_policy = 1;
198 }
199 *vif_priv = __vif_priv;
200
201 is_data_qos = ieee80211_is_data_qos(hdr->frame_control);
202
203 wcn36xx_set_tx_pdu(bd,
204 is_data_qos ?
205 sizeof(struct ieee80211_qos_hdr) :
206 sizeof(struct ieee80211_hdr_3addr),
207 skb->len, sta_priv ? sta_priv->tid : 0);
208
209 if (sta_priv && is_data_qos)
210 wcn36xx_tx_start_ampdu(wcn, sta_priv, skb);
211 }
212
213 static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd,
214 struct wcn36xx *wcn,
215 struct wcn36xx_vif **vif_priv,
216 struct sk_buff *skb,
217 bool bcast)
218 {
219 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
220 struct wcn36xx_vif *__vif_priv =
221 get_vif_by_addr(wcn, hdr->addr2);
222 bd->sta_index = __vif_priv->self_sta_index;
223 bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
224 bd->dpu_ne = 1;
225
226 /* default rate for unicast */
227 if (ieee80211_is_mgmt(hdr->frame_control))
228 bd->bd_rate = (WCN36XX_BAND(wcn) == IEEE80211_BAND_5GHZ) ?
229 WCN36XX_BD_RATE_CTRL :
230 WCN36XX_BD_RATE_MGMT;
231 else if (ieee80211_is_ctl(hdr->frame_control))
232 bd->bd_rate = WCN36XX_BD_RATE_CTRL;
233 else
234 wcn36xx_warn("frame control type unknown\n");
235
236 /*
237 * In joining state trick hardware that probe is sent as
238 * unicast even if address is broadcast.
239 */
240 if (__vif_priv->is_joining &&
241 ieee80211_is_probe_req(hdr->frame_control))
242 bcast = false;
243
244 if (bcast) {
245 /* broadcast */
246 bd->ub = 1;
247 /* No ack needed not unicast */
248 bd->ack_policy = 1;
249 bd->queue_id = WCN36XX_TX_B_WQ_ID;
250 } else
251 bd->queue_id = WCN36XX_TX_U_WQ_ID;
252 *vif_priv = __vif_priv;
253
254 wcn36xx_set_tx_pdu(bd,
255 ieee80211_is_data_qos(hdr->frame_control) ?
256 sizeof(struct ieee80211_qos_hdr) :
257 sizeof(struct ieee80211_hdr_3addr),
258 skb->len, WCN36XX_TID);
259 }
260
261 int wcn36xx_start_tx(struct wcn36xx *wcn,
262 struct wcn36xx_sta *sta_priv,
263 struct sk_buff *skb)
264 {
265 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
266 struct wcn36xx_vif *vif_priv = NULL;
267 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
268 unsigned long flags;
269 bool is_low = ieee80211_is_data(hdr->frame_control);
270 bool bcast = is_broadcast_ether_addr(hdr->addr1) ||
271 is_multicast_ether_addr(hdr->addr1);
272 struct wcn36xx_tx_bd *bd = wcn36xx_dxe_get_next_bd(wcn, is_low);
273
274 if (!bd) {
275 /*
276 * TX DXE are used in pairs. One for the BD and one for the
277 * actual frame. The BD DXE's has a preallocated buffer while
278 * the skb ones does not. If this isn't true something is really
279 * wierd. TODO: Recover from this situation
280 */
281
282 wcn36xx_err("bd address may not be NULL for BD DXE\n");
283 return -EINVAL;
284 }
285
286 memset(bd, 0, sizeof(*bd));
287
288 wcn36xx_dbg(WCN36XX_DBG_TX,
289 "tx skb %p len %d fc %04x sn %d %s %s\n",
290 skb, skb->len, __le16_to_cpu(hdr->frame_control),
291 IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)),
292 is_low ? "low" : "high", bcast ? "bcast" : "ucast");
293
294 wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len);
295
296 bd->dpu_rf = WCN36XX_BMU_WQ_TX;
297
298 bd->tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS);
299 if (bd->tx_comp) {
300 wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n");
301 spin_lock_irqsave(&wcn->dxe_lock, flags);
302 if (wcn->tx_ack_skb) {
303 spin_unlock_irqrestore(&wcn->dxe_lock, flags);
304 wcn36xx_warn("tx_ack_skb already set\n");
305 return -EINVAL;
306 }
307
308 wcn->tx_ack_skb = skb;
309 spin_unlock_irqrestore(&wcn->dxe_lock, flags);
310
311 /* Only one at a time is supported by fw. Stop the TX queues
312 * until the ack status gets back.
313 *
314 * TODO: Add watchdog in case FW does not answer
315 */
316 ieee80211_stop_queues(wcn->hw);
317 }
318
319 /* Data frames served first*/
320 if (is_low)
321 wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, skb, bcast);
322 else
323 /* MGMT and CTRL frames are handeld here*/
324 wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, skb, bcast);
325
326 buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
327 bd->tx_bd_sign = 0xbdbdbdbd;
328
329 return wcn36xx_dxe_tx_frame(wcn, vif_priv, skb, is_low);
330 } 1
2 #include <linux/kernel.h>
3 #include <linux/mutex.h>
4 #include <linux/spinlock.h>
5 #include <linux/errno.h>
6 #include <verifier/rcv.h>
7 #include <linux/list.h>
8
9 /* mutexes */
10 extern int mutex_lock_interruptible(struct mutex *lock);
11 extern int mutex_lock_killable(struct mutex *lock);
12 extern void mutex_lock(struct mutex *lock);
13
14 /* mutex model functions */
15 extern void ldv_mutex_lock(struct mutex *lock, char *sign);
16 extern int ldv_mutex_is_locked(struct mutex *lock, char *sign);
17 extern void ldv_mutex_unlock(struct mutex *lock, char *sign);
18
19
20 /* Spin locks */
21 extern void __ldv_spin_lock(spinlock_t *lock);
22 extern void __ldv_spin_unlock(spinlock_t *lock);
23 extern int __ldv_spin_trylock(spinlock_t *lock);
24 extern void __ldv_spin_unlock_wait(spinlock_t *lock);
25 extern void __ldv_spin_can_lock(spinlock_t *lock);
26 extern int __ldv_atomic_dec_and_lock(spinlock_t *lock);
27
28 /* spin model functions */
29 extern void ldv_spin_lock(spinlock_t *lock, char *sign);
30 extern void ldv_spin_unlock(spinlock_t *lock, char *sign);
31 extern int ldv_spin_is_locked(spinlock_t *lock, char *sign);
32
33 /* Support for list binder functions */
34 static inline struct list_head *ldv_list_get_first(struct list_head *head) {
35 return head->next;
36 }
37
38 static inline int ldv_list_is_stop(struct list_head *pos, struct list_head *head) {
39 return pos==head;
40 }
41
42 static inline struct list_head *ldv_list_get_next(struct list_head *pos) {
43 return pos->next;
44 }
45
46 #include <linux/mutex.h>
47 #include <linux/slab.h>
48 #include <linux/irqreturn.h>
49 #include <verifier/rcv.h>
50 #include <linux/rtnetlink.h>
51 #include <linux/gfp.h>
52 extern void* ldv_irq_data_2_1;
53 extern int ldv_irq_1_3=0;
54 extern int ldv_irq_line_2_2;
55 extern void* ldv_irq_data_1_1;
56 extern int ldv_irq_1_0=0;
57 extern int probed_5=0;
58 extern struct file *fops_wcn36xx_bmps_group2;
59 extern int ldv_state_variable_6;
60 extern void* ldv_irq_data_1_0;
61 extern int ldv_state_variable_0;
62 extern int ldv_state_variable_5;
63 extern int ldv_irq_line_2_1;
64 extern int ldv_state_variable_2;
65 extern int ldv_irq_2_0=0;
66 extern void* ldv_irq_data_1_3;
67 extern void* ldv_irq_data_1_2;
68 extern struct file *fops_wcn36xx_dump_group2;
69 extern void* ldv_irq_data_2_0;
70 extern struct inode *fops_wcn36xx_dump_group1;
71 extern int ldv_irq_1_2=0;
72 extern int LDV_IN_INTERRUPT = 1;
73 extern int ldv_irq_1_1=0;
74 extern int ldv_irq_2_3=0;
75 extern void* ldv_irq_data_2_3;
76 extern int ldv_irq_line_1_3;
77 extern int ldv_irq_2_2=0;
78 extern struct mutex fs_mutex;
79 extern int ldv_irq_line_2_0;
80 extern int ldv_state_variable_3;
81 extern int ldv_irq_line_1_0;
82 extern struct platform_device *wcn36xx_driver_group1;
83 extern struct mutex ar_mutex;
84 extern int ref_cnt;
85 extern struct mutex key_mtx;
86 extern int ldv_irq_line_1_1;
87 extern void* ldv_irq_data_2_2;
88 extern struct ieee80211_hw *wcn36xx_ops_group0;
89 extern int ldv_state_variable_1;
90 extern struct inode *fops_wcn36xx_bmps_group1;
91 extern int ldv_irq_line_1_2;
92 extern int ldv_state_variable_4;
93 extern int ldv_irq_line_2_3;
94 extern int ldv_irq_2_1=0;
95 extern void ldv_initialyze_ieee80211_ops_6(void);
96 extern int evil_hack_key_6(void);
97 extern void ldv_file_operations_3(void);
98 extern void choose_interrupt_2(void);
99 extern void disable_suitable_irq_2(int line, void * data);
100 extern int evil_hack_6(void);
101 extern void ldv_platform_probe_5(int (*probe)(struct platform_device *));
102 extern void activate_suitable_irq_2(int line, void * data);
103 extern void disable_suitable_irq_1(int line, void * data);
104 extern int reg_check_1(irqreturn_t (*handler)(int, void *));
105 extern void activate_suitable_irq_1(int line, void * data);
106 extern int ldv_irq_1(int state, int line, void *data);
107 extern int evil_hack_fs_lock(void);
108 extern int __VERIFIER_nondet_int(void);
109 extern void ldv_platform_driver_init_5(void);
110 extern int ldv_irq_2(int state, int line, void *data);
111 extern int evil_hack_ar_lock(void);
112 extern void choose_interrupt_1(void);
113 extern int reg_check_2(irqreturn_t (*handler)(int, void *));
114 extern void ldv_file_operations_4(void);
115 #line 1 "/work/ldvuser/andrianov/work/current--X--drivers/net/wireless/ath/wcn36xx/--X--defaultlinux-4.5-rc7--X--races--X--cpachecker/linux-4.5-rc7/csd_deg_dscv/19/dscv_tempdir/dscv/ri/races/drivers/net/wireless/ath/wcn36xx/txrx.c"
116 /*
117 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
118 *
119 * Permission to use, copy, modify, and/or distribute this software for any
120 * purpose with or without fee is hereby granted, provided that the above
121 * copyright notice and this permission notice appear in all copies.
122 *
123 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
124 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
125 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
126 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
127 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
128 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
129 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
130 */
131
132 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
133
134 #include "txrx.h"
135
136 static inline int get_rssi0(struct wcn36xx_rx_bd *bd)
137 {
138 return 100 - ((bd->phy_stat0 >> 24) & 0xff);
139 }
140
141 int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
142 {
143 struct ieee80211_rx_status status;
144 struct ieee80211_hdr *hdr;
145 struct wcn36xx_rx_bd *bd;
146 u16 fc, sn;
147
148 /*
149 * All fields must be 0, otherwise it can lead to
150 * unexpected consequences.
151 */
152 memset(&status, 0, sizeof(status));
153
154 bd = (struct wcn36xx_rx_bd *)skb->data;
155 buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
156 wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP,
157 "BD <<< ", (char *)bd,
158 sizeof(struct wcn36xx_rx_bd));
159
160 skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len);
161 skb_pull(skb, bd->pdu.mpdu_header_off);
162
163 status.mactime = 10;
164 status.freq = WCN36XX_CENTER_FREQ(wcn);
165 status.band = WCN36XX_BAND(wcn);
166 status.signal = -get_rssi0(bd);
167 status.antenna = 1;
168 status.rate_idx = 1;
169 status.flag = 0;
170 status.rx_flags = 0;
171 status.flag |= RX_FLAG_IV_STRIPPED |
172 RX_FLAG_MMIC_STRIPPED |
173 RX_FLAG_DECRYPTED;
174
175 wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag);
176
177 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
178
179 hdr = (struct ieee80211_hdr *) skb->data;
180 fc = __le16_to_cpu(hdr->frame_control);
181 sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
182
183 if (ieee80211_is_beacon(hdr->frame_control)) {
184 wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n",
185 skb, skb->len, fc, sn);
186 wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ",
187 (char *)skb->data, skb->len);
188 } else {
189 wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d\n",
190 skb, skb->len, fc, sn);
191 wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ",
192 (char *)skb->data, skb->len);
193 }
194
195 ieee80211_rx_irqsafe(wcn->hw, skb);
196
197 return 0;
198 }
199
200 static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd,
201 u32 mpdu_header_len,
202 u32 len,
203 u16 tid)
204 {
205 bd->pdu.mpdu_header_len = mpdu_header_len;
206 bd->pdu.mpdu_header_off = sizeof(*bd);
207 bd->pdu.mpdu_data_off = bd->pdu.mpdu_header_len +
208 bd->pdu.mpdu_header_off;
209 bd->pdu.mpdu_len = len;
210 bd->pdu.tid = tid;
211 bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS;
212 }
213
214 static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
215 u8 *addr)
216 {
217 struct wcn36xx_vif *vif_priv = NULL;
218 struct ieee80211_vif *vif = NULL;
219 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
220 vif = container_of((void *)vif_priv,
221 struct ieee80211_vif,
222 drv_priv);
223 if (memcmp(vif->addr, addr, ETH_ALEN) == 0)
224 return vif_priv;
225 }
226 wcn36xx_warn("vif %pM not found\n", addr);
227 return NULL;
228 }
229
230 static void wcn36xx_tx_start_ampdu(struct wcn36xx *wcn,
231 struct wcn36xx_sta *sta_priv,
232 struct sk_buff *skb)
233 {
234 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
235 struct ieee80211_sta *sta;
236 u8 *qc, tid;
237
238 if (!conf_is_ht(&wcn->hw->conf))
239 return;
240
241 sta = wcn36xx_priv_to_sta(sta_priv);
242
243 if (WARN_ON(!ieee80211_is_data_qos(hdr->frame_control)))
244 return;
245
246 if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
247 return;
248
249 qc = ieee80211_get_qos_ctl(hdr);
250 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
251
252 spin_lock(&sta_priv->ampdu_lock);
253 if (sta_priv->ampdu_state[tid] != WCN36XX_AMPDU_NONE)
254 goto out_unlock;
255
256 if (sta_priv->non_agg_frame_ct++ >= WCN36XX_AMPDU_START_THRESH) {
257 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
258 sta_priv->non_agg_frame_ct = 0;
259 ieee80211_start_tx_ba_session(sta, tid, 0);
260 }
261 out_unlock:
262 spin_unlock(&sta_priv->ampdu_lock);
263 }
264
265 static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
266 struct wcn36xx *wcn,
267 struct wcn36xx_vif **vif_priv,
268 struct wcn36xx_sta *sta_priv,
269 struct sk_buff *skb,
270 bool bcast)
271 {
272 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
273 struct ieee80211_vif *vif = NULL;
274 struct wcn36xx_vif *__vif_priv = NULL;
275 bool is_data_qos;
276
277 bd->bd_rate = WCN36XX_BD_RATE_DATA;
278
279 /*
280 * For not unicast frames mac80211 will not set sta pointer so use
281 * self_sta_index instead.
282 */
283 if (sta_priv) {
284 __vif_priv = sta_priv->vif;
285 vif = container_of((void *)__vif_priv,
286 struct ieee80211_vif,
287 drv_priv);
288
289 bd->dpu_sign = sta_priv->ucast_dpu_sign;
290 if (vif->type == NL80211_IFTYPE_STATION) {
291 bd->sta_index = sta_priv->bss_sta_index;
292 bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index;
293 } else if (vif->type == NL80211_IFTYPE_AP ||
294 vif->type == NL80211_IFTYPE_ADHOC ||
295 vif->type == NL80211_IFTYPE_MESH_POINT) {
296 bd->sta_index = sta_priv->sta_index;
297 bd->dpu_desc_idx = sta_priv->dpu_desc_index;
298 }
299 } else {
300 __vif_priv = get_vif_by_addr(wcn, hdr->addr2);
301 bd->sta_index = __vif_priv->self_sta_index;
302 bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
303 bd->dpu_sign = __vif_priv->self_ucast_dpu_sign;
304 }
305
306 if (ieee80211_is_nullfunc(hdr->frame_control) ||
307 (sta_priv && !sta_priv->is_data_encrypted))
308 bd->dpu_ne = 1;
309
310 if (bcast) {
311 bd->ub = 1;
312 bd->ack_policy = 1;
313 }
314 *vif_priv = __vif_priv;
315
316 is_data_qos = ieee80211_is_data_qos(hdr->frame_control);
317
318 wcn36xx_set_tx_pdu(bd,
319 is_data_qos ?
320 sizeof(struct ieee80211_qos_hdr) :
321 sizeof(struct ieee80211_hdr_3addr),
322 skb->len, sta_priv ? sta_priv->tid : 0);
323
324 if (sta_priv && is_data_qos)
325 wcn36xx_tx_start_ampdu(wcn, sta_priv, skb);
326 }
327
328 static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd,
329 struct wcn36xx *wcn,
330 struct wcn36xx_vif **vif_priv,
331 struct sk_buff *skb,
332 bool bcast)
333 {
334 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
335 struct wcn36xx_vif *__vif_priv =
336 get_vif_by_addr(wcn, hdr->addr2);
337 bd->sta_index = __vif_priv->self_sta_index;
338 bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
339 bd->dpu_ne = 1;
340
341 /* default rate for unicast */
342 if (ieee80211_is_mgmt(hdr->frame_control))
343 bd->bd_rate = (WCN36XX_BAND(wcn) == IEEE80211_BAND_5GHZ) ?
344 WCN36XX_BD_RATE_CTRL :
345 WCN36XX_BD_RATE_MGMT;
346 else if (ieee80211_is_ctl(hdr->frame_control))
347 bd->bd_rate = WCN36XX_BD_RATE_CTRL;
348 else
349 wcn36xx_warn("frame control type unknown\n");
350
351 /*
352 * In joining state trick hardware that probe is sent as
353 * unicast even if address is broadcast.
354 */
355 if (__vif_priv->is_joining &&
356 ieee80211_is_probe_req(hdr->frame_control))
357 bcast = false;
358
359 if (bcast) {
360 /* broadcast */
361 bd->ub = 1;
362 /* No ack needed not unicast */
363 bd->ack_policy = 1;
364 bd->queue_id = WCN36XX_TX_B_WQ_ID;
365 } else
366 bd->queue_id = WCN36XX_TX_U_WQ_ID;
367 *vif_priv = __vif_priv;
368
369 wcn36xx_set_tx_pdu(bd,
370 ieee80211_is_data_qos(hdr->frame_control) ?
371 sizeof(struct ieee80211_qos_hdr) :
372 sizeof(struct ieee80211_hdr_3addr),
373 skb->len, WCN36XX_TID);
374 }
375
376 int wcn36xx_start_tx(struct wcn36xx *wcn,
377 struct wcn36xx_sta *sta_priv,
378 struct sk_buff *skb)
379 {
380 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
381 struct wcn36xx_vif *vif_priv = NULL;
382 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
383 unsigned long flags;
384 bool is_low = ieee80211_is_data(hdr->frame_control);
385 bool bcast = is_broadcast_ether_addr(hdr->addr1) ||
386 is_multicast_ether_addr(hdr->addr1);
387 struct wcn36xx_tx_bd *bd = wcn36xx_dxe_get_next_bd(wcn, is_low);
388
389 if (!bd) {
390 /*
391 * TX DXE are used in pairs. One for the BD and one for the
392 * actual frame. The BD DXE's has a preallocated buffer while
393 * the skb ones does not. If this isn't true something is really
394 * wierd. TODO: Recover from this situation
395 */
396
397 wcn36xx_err("bd address may not be NULL for BD DXE\n");
398 return -EINVAL;
399 }
400
401 memset(bd, 0, sizeof(*bd));
402
403 wcn36xx_dbg(WCN36XX_DBG_TX,
404 "tx skb %p len %d fc %04x sn %d %s %s\n",
405 skb, skb->len, __le16_to_cpu(hdr->frame_control),
406 IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)),
407 is_low ? "low" : "high", bcast ? "bcast" : "ucast");
408
409 wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len);
410
411 bd->dpu_rf = WCN36XX_BMU_WQ_TX;
412
413 bd->tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS);
414 if (bd->tx_comp) {
415 wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n");
416 spin_lock_irqsave(&wcn->dxe_lock, flags);
417 if (wcn->tx_ack_skb) {
418 spin_unlock_irqrestore(&wcn->dxe_lock, flags);
419 wcn36xx_warn("tx_ack_skb already set\n");
420 return -EINVAL;
421 }
422
423 wcn->tx_ack_skb = skb;
424 spin_unlock_irqrestore(&wcn->dxe_lock, flags);
425
426 /* Only one at a time is supported by fw. Stop the TX queues
427 * until the ack status gets back.
428 *
429 * TODO: Add watchdog in case FW does not answer
430 */
431 ieee80211_stop_queues(wcn->hw);
432 }
433
434 /* Data frames served first*/
435 if (is_low)
436 wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, skb, bcast);
437 else
438 /* MGMT and CTRL frames are handeld here*/
439 wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, skb, bcast);
440
441 buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
442 bd->tx_bd_sign = 0xbdbdbdbd;
443
444 return wcn36xx_dxe_tx_frame(wcn, vif_priv, skb, is_low);
445 }
446
447 #line 115 "/work/ldvuser/andrianov/work/current--X--drivers/net/wireless/ath/wcn36xx/--X--defaultlinux-4.5-rc7--X--races--X--cpachecker/linux-4.5-rc7/csd_deg_dscv/19/dscv_tempdir/dscv/ri/races/drivers/net/wireless/ath/wcn36xx/txrx.o.c.prepared" 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 #ifndef _WCN36XX_H_
18 #define _WCN36XX_H_
19
20 #include <linux/completion.h>
21 #include <linux/printk.h>
22 #include <linux/spinlock.h>
23 #include <net/mac80211.h>
24
25 #include "hal.h"
26 #include "smd.h"
27 #include "txrx.h"
28 #include "dxe.h"
29 #include "pmc.h"
30 #include "debug.h"
31
32 #define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin"
33 #define WCN36XX_AGGR_BUFFER_SIZE 64
34
35 /* How many frames until we start a-mpdu TX session */
36 #define WCN36XX_AMPDU_START_THRESH 20
37
38 extern unsigned int wcn36xx_dbg_mask;
39
40 enum wcn36xx_debug_mask {
41 WCN36XX_DBG_DXE = 0x00000001,
42 WCN36XX_DBG_DXE_DUMP = 0x00000002,
43 WCN36XX_DBG_SMD = 0x00000004,
44 WCN36XX_DBG_SMD_DUMP = 0x00000008,
45 WCN36XX_DBG_RX = 0x00000010,
46 WCN36XX_DBG_RX_DUMP = 0x00000020,
47 WCN36XX_DBG_TX = 0x00000040,
48 WCN36XX_DBG_TX_DUMP = 0x00000080,
49 WCN36XX_DBG_HAL = 0x00000100,
50 WCN36XX_DBG_HAL_DUMP = 0x00000200,
51 WCN36XX_DBG_MAC = 0x00000400,
52 WCN36XX_DBG_BEACON = 0x00000800,
53 WCN36XX_DBG_BEACON_DUMP = 0x00001000,
54 WCN36XX_DBG_PMC = 0x00002000,
55 WCN36XX_DBG_PMC_DUMP = 0x00004000,
56 WCN36XX_DBG_ANY = 0xffffffff,
57 };
58
59 #define wcn36xx_err(fmt, arg...) \
60 printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg)
61
62 #define wcn36xx_warn(fmt, arg...) \
63 printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg)
64
65 #define wcn36xx_info(fmt, arg...) \
66 printk(KERN_INFO pr_fmt(fmt), ##arg)
67
68 #define wcn36xx_dbg(mask, fmt, arg...) do { \
69 if (wcn36xx_dbg_mask & mask) \
70 printk(KERN_DEBUG pr_fmt(fmt), ##arg); \
71 } while (0)
72
73 #define wcn36xx_dbg_dump(mask, prefix_str, buf, len) do { \
74 if (wcn36xx_dbg_mask & mask) \
75 print_hex_dump(KERN_DEBUG, pr_fmt(prefix_str), \
76 DUMP_PREFIX_OFFSET, 32, 1, \
77 buf, len, false); \
78 } while (0)
79
80 enum wcn36xx_ampdu_state {
81 WCN36XX_AMPDU_NONE,
82 WCN36XX_AMPDU_INIT,
83 WCN36XX_AMPDU_START,
84 WCN36XX_AMPDU_OPERATIONAL,
85 };
86
87 #define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value)
88 #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band)
89 #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq)
90 #define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval)
91 #define WCN36XX_FLAGS(__wcn) (__wcn->hw->flags)
92 #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power)
93
94 static inline void buff_to_be(u32 *buf, size_t len)
95 {
96 int i;
97 for (i = 0; i < len; i++)
98 buf[i] = cpu_to_be32(buf[i]);
99 }
100
101 struct nv_data {
102 int is_valid;
103 u8 table;
104 };
105
106 /* Interface for platform control path
107 *
108 * @open: hook must be called when wcn36xx wants to open control channel.
109 * @tx: sends a buffer.
110 */
111 struct wcn36xx_platform_ctrl_ops {
112 int (*open)(void *drv_priv, void *rsp_cb);
113 void (*close)(void);
114 int (*tx)(char *buf, size_t len);
115 int (*get_hw_mac)(u8 *addr);
116 int (*smsm_change_state)(u32 clear_mask, u32 set_mask);
117 };
118
119 /**
120 * struct wcn36xx_vif - holds VIF related fields
121 *
122 * @bss_index: bss_index is initially set to 0xFF. bss_index is received from
123 * HW after first config_bss call and must be used in delete_bss and
124 * enter/exit_bmps.
125 */
126 struct wcn36xx_vif {
127 struct list_head list;
128 struct wcn36xx_sta *sta;
129 u8 dtim_period;
130 enum ani_ed_type encrypt_type;
131 bool is_joining;
132 struct wcn36xx_hal_mac_ssid ssid;
133
134 /* Power management */
135 enum wcn36xx_power_state pw_state;
136
137 u8 bss_index;
138 /* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */
139 u8 self_sta_index;
140 u8 self_dpu_desc_index;
141 u8 self_ucast_dpu_sign;
142 };
143
144 /**
145 * struct wcn36xx_sta - holds STA related fields
146 *
147 * @tid: traffic ID that is used during AMPDU and in TX BD.
148 * @sta_index: STA index is returned from HW after config_sta call and is
149 * used in both SMD channel and TX BD.
150 * @dpu_desc_index: DPU descriptor index is returned from HW after config_sta
151 * call and is used in TX BD.
152 * @bss_sta_index: STA index is returned from HW after config_bss call and is
153 * used in both SMD channel and TX BD. See table bellow when it is used.
154 * @bss_dpu_desc_index: DPU descriptor index is returned from HW after
155 * config_bss call and is used in TX BD.
156 * ______________________________________________
157 * | | STA | AP |
158 * |______________|_____________|_______________|
159 * | TX BD |bss_sta_index| sta_index |
160 * |______________|_____________|_______________|
161 * |all SMD calls |bss_sta_index| sta_index |
162 * |______________|_____________|_______________|
163 * |smd_delete_sta| sta_index | sta_index |
164 * |______________|_____________|_______________|
165 */
166 struct wcn36xx_sta {
167 struct wcn36xx_vif *vif;
168 u16 aid;
169 u16 tid;
170 u8 sta_index;
171 u8 dpu_desc_index;
172 u8 ucast_dpu_sign;
173 u8 bss_sta_index;
174 u8 bss_dpu_desc_index;
175 bool is_data_encrypted;
176 /* Rates */
177 struct wcn36xx_hal_supported_rates supported_rates;
178
179 spinlock_t ampdu_lock; /* protects next two fields */
180 enum wcn36xx_ampdu_state ampdu_state[16];
181 int non_agg_frame_ct;
182 };
183 struct wcn36xx_dxe_ch;
184 struct wcn36xx {
185 struct ieee80211_hw *hw;
186 struct device *dev;
187 struct list_head vif_list;
188
189 const struct firmware *nv;
190
191 u8 fw_revision;
192 u8 fw_version;
193 u8 fw_minor;
194 u8 fw_major;
195 u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
196 u32 chip_version;
197
198 /* extra byte for the NULL termination */
199 u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
200 u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1];
201
202 /* IRQs */
203 int tx_irq;
204 int rx_irq;
205 void __iomem *mmio;
206
207 struct wcn36xx_platform_ctrl_ops *ctrl_ops;
208 /*
209 * smd_buf must be protected with smd_mutex to garantee
210 * that all messages are sent one after another
211 */
212 u8 *hal_buf;
213 size_t hal_rsp_len;
214 struct mutex hal_mutex;
215 struct completion hal_rsp_compl;
216 struct workqueue_struct *hal_ind_wq;
217 struct work_struct hal_ind_work;
218 struct mutex hal_ind_mutex;
219 struct list_head hal_ind_queue;
220
221 /* DXE channels */
222 struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */
223 struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */
224 struct wcn36xx_dxe_ch dxe_rx_l_ch; /* RX low */
225 struct wcn36xx_dxe_ch dxe_rx_h_ch; /* RX high */
226
227 /* For synchronization of DXE resources from BH, IRQ and WQ contexts */
228 spinlock_t dxe_lock;
229 bool queues_stopped;
230
231 /* Memory pools */
232 struct wcn36xx_dxe_mem_pool mgmt_mem_pool;
233 struct wcn36xx_dxe_mem_pool data_mem_pool;
234
235 struct sk_buff *tx_ack_skb;
236
237 #ifdef CONFIG_WCN36XX_DEBUGFS
238 /* Debug file system entry */
239 struct wcn36xx_dfs_entry dfs;
240 #endif /* CONFIG_WCN36XX_DEBUGFS */
241
242 };
243
244 #define WCN36XX_CHIP_3660 0
245 #define WCN36XX_CHIP_3680 1
246
247 static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
248 u8 major,
249 u8 minor,
250 u8 version,
251 u8 revision)
252 {
253 return (wcn->fw_major == major &&
254 wcn->fw_minor == minor &&
255 wcn->fw_version == version &&
256 wcn->fw_revision == revision);
257 }
258 void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates);
259
260 static inline
261 struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv)
262 {
263 return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv);
264 }
265
266 #endif /* _WCN36XX_H_ */ 1 #ifndef _LDV_RCV_H_
2 #define _LDV_RCV_H_
3
4 /* If expr evaluates to zero, ldv_assert() causes a program to reach the error
5 label like the standard assert(). */
6 #define ldv_assert(expr) ((expr) ? 0 : ldv_error())
7
8 /* The error label wrapper. It is used because of some static verifiers (like
9 BLAST) don't accept multiple error labels through a program. */
10 static inline void ldv_error(void)
11 {
12 LDV_ERROR: goto LDV_ERROR;
13 }
14
15 /* If expr evaluates to zero, ldv_assume() causes an infinite loop that is
16 avoided by verifiers. */
17 #define ldv_assume(expr) ((expr) ? 0 : ldv_stop())
18
19 /* Infinite loop, that causes verifiers to skip such paths. */
20 static inline void ldv_stop(void) {
21 LDV_STOP: goto LDV_STOP;
22 }
23
24 /* Special nondeterministic functions. */
25 int ldv_undef_int(void);
26 void *ldv_undef_ptr(void);
27 unsigned long ldv_undef_ulong(void);
28 long ldv_undef_long(void);
29 /* Return nondeterministic negative integer number. */
30 static inline int ldv_undef_int_negative(void)
31 {
32 int ret = ldv_undef_int();
33
34 ldv_assume(ret < 0);
35
36 return ret;
37 }
38 /* Return nondeterministic nonpositive integer number. */
39 static inline int ldv_undef_int_nonpositive(void)
40 {
41 int ret = ldv_undef_int();
42
43 ldv_assume(ret <= 0);
44
45 return ret;
46 }
47
48 /* Add explicit model for __builin_expect GCC function. Without the model a
49 return value will be treated as nondetermined by verifiers. */
50 static inline long __builtin_expect(long exp, long c)
51 {
52 return exp;
53 }
54
55 /* This function causes the program to exit abnormally. GCC implements this
56 function by using a target-dependent mechanism (such as intentionally executing
57 an illegal instruction) or by calling abort. The mechanism used may vary from
58 release to release so you should not rely on any particular implementation.
59 http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */
60 static inline void __builtin_trap(void)
61 {
62 ldv_assert(0);
63 }
64
65 /* The constant is for simulating an error of ldv_undef_ptr() function. */
66 #define LDV_PTR_MAX 2012
67
68 #endif /* _LDV_RCV_H_ */ |
Here is an explanation of a rule violation arisen while checking your driver against a corresponding kernel.
Note that it may be false positive, i.e. there isn't a real error indeed. Please analyze a given error trace and related source code to understand whether there is an error in your driver.
Error trace column contains a path on which the given rule is violated. You can expand/collapse some entity classes by clicking on corresponding checkboxes in a main menu or in an advanced Others menu. Also you can expand/collapse each particular entity by clicking on +/-. In hovering on some entities you can see some tips. Also the error trace is bound with related source code. Line numbers may be shown as links on the left. You can click on them to open corresponding lines in source code.
Source code column contains a content of files related with the error trace. There is source code of your driver (note that there are some LDV modifications at the end), kernel headers and rule model. Tabs show a currently opened file and other available files. In hovering on them you can see full file names. On clicking a corresponding file content will be shown.
Ядро | Модуль | Правило | Верификатор | Вердикт | Статус | Время создания |
linux-4.5-rc7 | drivers/net/wireless/ath/wcn36xx/wcn36xx.ko | races | CPAchecker | Bug | Unreported | 2016-03-14 19:13:56 |
Комментарий
Updating of the struct sta_priv is performed without locks. we can partially write the new values and read inconsistent ones.
[В начало]