Error Trace

[Home]

Bug # 119

Show/hide error trace
Error trace
Function bodies
Blocks
  • Others...
    Function bodies without model function calls
    Initialization function calls
    Initialization function bodies
    Entry point
    Entry point body
    Function calls
    Skipped function calls
    Formal parameter names
    Declarations
    Assumes
    Assume conditions
    Returns
    Return values
    DEG initialization
    DEG function calls
    Model function calls
    Model function bodies
    Model asserts
    Model state changes
    Model function function calls
    Model function function bodies
    Model returns
    Model others
    Identation
    Line numbers
    Expand signs
/*Is true unsafe:*/
/*Number of usage points:2*/
/*Number of usages :2*/
/*Two examples:*/
/*_____________________*/
/*mutex_lock(char *"_hal_mutex_of_wcn36xx")[1], rtnl_lock[1]*/
-__CPAchecker_initialize()
{
return ;
}
-entry_point
{
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);
225 assume(tmp == 0);
228 assume(ldv_state_variable_6 != 0);
229 tmp___0 = __VERIFIER_nondet_int() { /* Function call is skipped due to function is undefined */}
229 switch (tmp___0);
230 assume(!(tmp___0 == 0));
243 assume(!(tmp___0 == 1));
260 assume(!(tmp___0 == 2));
270 assume(!(tmp___0 == 3));
287 assume(!(tmp___0 == 4));
304 assume(!(tmp___0 == 5));
321 assume(!(tmp___0 == 6));
338 assume(!(tmp___0 == 7));
350 assume(!(tmp___0 == 8));
367 assume(!(tmp___0 == 9));
384 assume(!(tmp___0 == 10));
401 assume(!(tmp___0 == 11));
411 assume(!(tmp___0 == 12));
428 assume(!(tmp___0 == 13));
445 assume(tmp___0 == 14);
447 assume(ldv_state_variable_6 == 2);
447 -evil_hack_6()
{
/*Change states for locks rtnl_lock*/
136 rtnl_lock() { /* Function call is skipped due to function is undefined */}
137 return 1;;
}
447 assume(tmp___5 != 0);
449 -wcn36xx_add_interface(wcn36xx_ops_group0, ldvarg3)
{
769 struct wcn36xx *wcn;
770 struct wcn36xx_vif *vif_priv;
770 struct wcn36xx *__CPAchecker_TMP_0 = (struct wcn36xx *)(hw->priv);
770 wcn = __CPAchecker_TMP_0;
771 vif_priv = (struct wcn36xx_vif *)(&(vif->drv_priv));
773 assume(!((wcn36xx_dbg_mask & 1024U) != 0U));
776 unsigned int __CPAchecker_TMP_2 = (unsigned int)(vif->type);
776 assume(!(__CPAchecker_TMP_2 != 2U));
785 -list_add(&(vif_priv->list), &(wcn->vif_list))
{
63 __list_add(new, head, head->next) { /* Function call is skipped due to function is undefined */}
64 return ;;
}
786 -wcn36xx_smd_add_sta_self(wcn, vif)
{
754 struct wcn36xx_hal_add_sta_self_req msg_body;
755 int ret;
755 ret = 0;
757 -ldv_mutex_lock_290(&(wcn->hal_mutex))
{
/*Change states for locks mutex_lock(char *"_hal_mutex_of_wcn36xx")*/
606 ldv_mutex_lock(ldv_func_arg1, (char *)"_hal_mutex_of_wcn36xx") { /* Function call is skipped due to function is undefined */}
607 return ;;
}
758 __memset((void *)(&msg_body), 0, 18UL) { /* Function call is skipped due to function is undefined */}
758 msg_body.header.msg_type = 125U;
758 msg_body.header.msg_version = 0U;
758 msg_body.header.len = 18U;
760 __memcpy((void *)(&(msg_body.self_addr)), (const void *)(&(vif->addr)), 6UL) { /* Function call is skipped due to function is undefined */}
762 void *__CPAchecker_TMP_0 = (void *)(wcn->hal_buf);
762 __memset(__CPAchecker_TMP_0, 0, (size_t )(msg_body.header.len)) { /* Function call is skipped due to function is undefined */}
762 void *__CPAchecker_TMP_1 = (void *)(wcn->hal_buf);
762 __memcpy(__CPAchecker_TMP_1, (const void *)(&msg_body), 18UL) { /* Function call is skipped due to function is undefined */}
764 assume(!((wcn36xx_dbg_mask & 256U) != 0U));
768 -wcn36xx_smd_send_and_wait(wcn, (size_t )(msg_body.header.len))
{
250 int ret;
251 unsigned long start;
252 unsigned long tmp;
253 unsigned long tmp___0;
254 unsigned int tmp___1;
250 ret = 0;
252 assume(!((wcn36xx_dbg_mask & 8U) != 0U));
254 -init_completion(&(wcn->hal_rsp_compl))
{
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);
257 assume(!(ret != 0));
261 -msecs_to_jiffies(500U)
{
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 */}
261 assume(!(tmp___0 == 0UL));
268 assume(!((wcn36xx_dbg_mask & 4U) != 0U));
272 out:;
271 return ret;;
}
769 assume(!(ret != 0));
773 void *__CPAchecker_TMP_2 = (void *)(wcn->hal_buf);
773 -wcn36xx_smd_add_sta_self_rsp(wcn, vif, __CPAchecker_TMP_2, wcn->hal_rsp_len)
{
726 struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
727 struct wcn36xx_vif *priv_vif;
729 priv_vif = (struct wcn36xx_vif *)(&(vif->drv_priv));
731 assume(!(len <= 14UL));
734 rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf;
736 assume(!((rsp->status) != 0U));
742 assume(!((wcn36xx_dbg_mask & 256U) != 0U));
746 priv_vif->self_sta_index = rsp->self_sta_index;
747 priv_vif->self_dpu_desc_index = rsp->dpu_index;
749 return 0;;
}
return ;;
}
return ;;
}
return ;;
}
/*_____________________*/
/*Without locks*/
-__CPAchecker_initialize()
{
return ;
}
-entry_point
{
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);
225 assume(tmp == 0);
228 assume(ldv_state_variable_6 != 0);
229 tmp___0 = __VERIFIER_nondet_int() { /* Function call is skipped due to function is undefined */}
229 switch (tmp___0);
230 assume(!(tmp___0 == 0));
243 assume(!(tmp___0 == 1));
260 assume(!(tmp___0 == 2));
270 assume(!(tmp___0 == 3));
287 assume(!(tmp___0 == 4));
304 assume(!(tmp___0 == 5));
321 assume(!(tmp___0 == 6));
338 assume(!(tmp___0 == 7));
350 assume(tmp___0 == 8);
352 assume(ldv_state_variable_6 == 1);
354 -wcn36xx_tx(wcn36xx_ops_group0, ldvarg18, ldvarg17)
{
373 struct wcn36xx *wcn;
374 struct wcn36xx_sta *sta_priv;
375 int tmp;
374 struct wcn36xx *__CPAchecker_TMP_0 = (struct wcn36xx *)(hw->priv);
374 wcn = __CPAchecker_TMP_0;
375 sta_priv = (struct wcn36xx_sta *)0;
377 unsigned long __CPAchecker_TMP_1 = (unsigned long)(control->sta);
377 assume(!(__CPAchecker_TMP_1 != ((unsigned long)((struct ieee80211_sta *)0))));
380 -wcn36xx_start_tx(wcn, sta_priv, skb)
{
263 struct ieee80211_hdr *hdr;
264 struct wcn36xx_vif *vif_priv;
265 struct ieee80211_tx_info *info;
266 struct ieee80211_tx_info *tmp;
267 unsigned long flags;
268 _Bool is_low;
269 _Bool tmp___0;
270 _Bool bcast;
271 _Bool tmp___1;
272 _Bool tmp___2;
273 int tmp___3;
274 struct wcn36xx_tx_bd *bd;
275 void *tmp___4;
276 int tmp___5;
265 struct ieee80211_hdr *__CPAchecker_TMP_0 = (struct ieee80211_hdr *)(skb->data);
265 hdr = __CPAchecker_TMP_0;
266 vif_priv = (struct wcn36xx_vif *)0;
267 -IEEE80211_SKB_CB(skb)
{
925 return (struct ieee80211_tx_info *)(&(skb->cb));;
}
267 info = tmp;
269 int __CPAchecker_TMP_1 = (int)(hdr->frame_control);
269 -ieee80211_is_data(__CPAchecker_TMP_1)
{
357 return (((int)fc) & 12) == 8;;
}
269 is_low = tmp___0;
270 -is_broadcast_ether_addr((u8 *)(&(hdr->addr1)))
{
162 return ((unsigned int)((((int)((unsigned short)(*((u16 *)addr)))) & ((int)((unsigned short)(*(((u16 *)addr) + 2U))))) & ((int)((unsigned short)(*(((u16 *)addr) + 4U)))))) == 65535U;;
}
270 assume(!(((int)tmp___1) == 0));
270 tmp___3 = 1;
270 bcast = (bool )tmp___3;
272 -wcn36xx_dxe_get_next_bd(wcn, (int)is_low)
{
31 struct wcn36xx_dxe_ch *ch;
31 struct wcn36xx_dxe_ch *__CPAchecker_TMP_0;
31 assume(!(((int)is_low) == 0));
31 __CPAchecker_TMP_0 = &(wcn->dxe_tx_l_ch);
31 ch = __CPAchecker_TMP_0;
35 return ch->head_blk_ctl->bd_cpu_addr;;
}
272 bd = (struct wcn36xx_tx_bd *)tmp___4;
274 assume(!(((unsigned long)bd) == ((unsigned long)((struct wcn36xx_tx_bd *)0))));
286 __memset((void *)bd, 0, 40UL) { /* Function call is skipped due to function is undefined */}
288 assume(!((wcn36xx_dbg_mask & 64U) != 0U));
294 assume(!((wcn36xx_dbg_mask & 128U) != 0U));
296 bd->dpu_rf = 25U;
298 unsigned char __CPAchecker_TMP_8 = (unsigned char)(info->flags);
298 bd->tx_comp = ((unsigned int)__CPAchecker_TMP_8) & 1U;
299 assume(!(((unsigned int)(*(((unsigned char *)bd) + 0UL))) != 0U));
320 assume(!(((int)is_low) == 0));
321 -wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, skb, (int)bcast)
{
154 struct ieee80211_hdr *hdr;
155 struct ieee80211_vif *vif;
156 struct wcn36xx_vif *__vif_priv;
157 _Bool is_data_qos;
158 u8 (*__mptr)[0U];
159 _Bool tmp;
157 struct ieee80211_hdr *__CPAchecker_TMP_0 = (struct ieee80211_hdr *)(skb->data);
157 hdr = __CPAchecker_TMP_0;
158 vif = (struct ieee80211_vif *)0;
159 __vif_priv = (struct wcn36xx_vif *)0;
162 bd->bd_rate = 0U;
168 assume(!(((unsigned long)sta_priv) != ((unsigned long)((struct wcn36xx_sta *)0))));
185 -get_vif_by_addr(wcn, (u8 *)(&(hdr->addr2)))
{
101 struct wcn36xx_vif *vif_priv;
102 struct ieee80211_vif *vif;
103 const struct list_head *__mptr;
104 u8 (*__mptr___0)[0U];
105 int tmp;
106 const struct list_head *__mptr___1;
102 vif_priv = (struct wcn36xx_vif *)0;
103 vif = (struct ieee80211_vif *)0;
104 __mptr = (const struct list_head *)(wcn->vif_list.next);
104 vif_priv = (struct wcn36xx_vif *)__mptr;
104 goto ldv_54820;
104 assume(!(((unsigned long)(&(vif_priv->list))) != ((unsigned long)(&(wcn->vif_list)))));
111 printk("\fwcn36xx: WARNING vif %pM not found\n", addr) { /* Function call is skipped due to function is undefined */}
112 return (struct wcn36xx_vif *)0;;
}
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;
return ;;
}
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 &reg_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, &reg_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, &reg_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 &reg_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, &reg_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, &reg_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.

Kernel Module Rule Verifier Verdict Status Timestamp
linux-4.5-rc7 drivers/net/wireless/ath/wcn36xx/wcn36xx.ko races CPAchecker Unknown Unreported 2016-03-14 19:19:12

Comment

Is it possible that sta_priv and priv_vix points to the same memory?

[Home]