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