diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index df241dd983ad..c053d55671aa 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -851,6 +851,99 @@ QDF_STATUS hdd_softap_deinit_tx_rx(struct hdd_adapter *adapter) return QDF_STATUS_SUCCESS; } +static void +hdd_reset_sta_info_during_reattach(struct hdd_station_info *sta_info) +{ + sta_info->in_use = 0; + sta_info->sta_id = 0; + sta_info->sta_type = 0; + qdf_mem_zero(&sta_info->sta_mac, QDF_MAC_ADDR_SIZE); + sta_info->peer_state = 0; + sta_info->is_qos_enabled = 0; + sta_info->is_deauth_in_progress = 0; + sta_info->nss = 0; + sta_info->rate_flags = 0; + sta_info->ecsa_capable = 0; + sta_info->max_phy_rate = 0; + sta_info->tx_packets = 0; + sta_info->tx_bytes = 0; + sta_info->rx_packets = 0; + sta_info->rx_bytes = 0; + sta_info->last_tx_rx_ts = 0; + sta_info->assoc_ts = 0; + sta_info->disassoc_ts = 0; + sta_info->tx_rate = 0; + sta_info->rx_rate = 0; + sta_info->ampdu = 0; + sta_info->sgi_enable = 0; + sta_info->tx_stbc = 0; + sta_info->rx_stbc = 0; + sta_info->ch_width = 0; + sta_info->mode = 0; + sta_info->max_supp_idx = 0; + sta_info->max_ext_idx = 0; + sta_info->max_mcs_idx = 0; + sta_info->rx_mcs_map = 0; + sta_info->tx_mcs_map = 0; + sta_info->freq = 0; + sta_info->dot11_mode = 0; + sta_info->ht_present = 0; + sta_info->vht_present = 0; + qdf_mem_zero(&sta_info->ht_caps, sizeof(sta_info->ht_caps)); + qdf_mem_zero(&sta_info->vht_caps, sizeof(sta_info->vht_caps)); + sta_info->reason_code = 0; + sta_info->rssi = 0; + sta_info->dhcp_phase = 0; + sta_info->dhcp_nego_status = 0; + sta_info->capability = 0; + sta_info->support_mode = 0; + sta_info->rx_retry_cnt = 0; + sta_info->rx_mc_bc_cnt = 0; + + if (sta_info->assoc_req_ies.len) { + qdf_mem_free(sta_info->assoc_req_ies.data); + sta_info->assoc_req_ies.data = NULL; + sta_info->assoc_req_ies.len = 0; + } + + sta_info->pending_eap_frm_type = 0; +} + +/** + * hdd_sta_info_re_attach() - Re-Attach the station info structure into the list + * @sta_info_container: The station info container obj that stores and maintains + * the sta_info obj. + * @sta_info: The station info structure that is to be attached to the + * container object. + * + * This function re-attaches the station if it gets re-connect after + * disconnecting and before its all references are released. + * + * Return: QDF STATUS SUCCESS on successful attach, error code otherwise + */ +static QDF_STATUS hdd_sta_info_re_attach( + struct hdd_sta_info_obj *sta_info_container, + struct hdd_station_info *sta_info, + struct qdf_mac_addr *sta_mac) +{ + if (!sta_info_container || !sta_info) { + hdd_err("Parameter(s) null"); + return QDF_STATUS_E_INVAL; + } + + qdf_spin_lock_bh(&sta_info_container->sta_obj_lock); + + hdd_reset_sta_info_during_reattach(sta_info); + + /* Add one extra ref for reattach */ + qdf_atomic_inc(&sta_info->ref_cnt); + qdf_mem_copy(&sta_info->sta_mac, sta_mac, sizeof(struct qdf_mac_addr)); + + qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock); + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS hdd_softap_init_tx_rx_sta(struct hdd_adapter *adapter, struct qdf_mac_addr *sta_mac) { @@ -863,8 +956,10 @@ QDF_STATUS hdd_softap_init_tx_rx_sta(struct hdd_adapter *adapter, if (sta_info) { hdd_err("Reinit of in use station " QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(sta_mac->bytes)); + status = hdd_sta_info_re_attach(&adapter->sta_info_list, + sta_info, sta_mac); hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true); - return QDF_STATUS_E_FAILURE; + return status; } sta_info = qdf_mem_malloc(sizeof(struct hdd_station_info)); @@ -1133,19 +1228,6 @@ QDF_STATUS hdd_softap_register_sta(struct hdd_adapter *adapter, ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); - /* - * Clean up old entry if it is not cleaned up properly - */ - - sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, - sta_mac->bytes); - if (sta_info) { - hdd_debug("clean up old entry for STA MAC " QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(sta_mac->bytes)); - hdd_softap_deregister_sta(adapter, &sta_info); - hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true); - } - /* * If the address is a broadcast address, then provide the self mac addr * to the data path. Else provide the mac address of the connected peer.