diff options
author | Ashish Kumar Dhanotiya <adhanoti@codeaurora.org> | 2018-10-12 21:13:57 +0530 |
---|---|---|
committer | Victor Hsu <hsuvictor@google.com> | 2019-05-24 07:21:44 +0000 |
commit | 568347358ef99e8b8946d9e184a4e80774e07212 (patch) | |
tree | 0748aa528004b09668aab74d9f646af78bc79e18 | |
parent | 0371413c87b552b7d93df37ac169dfb4d1b1fe6a (diff) | |
download | qcacld-568347358ef99e8b8946d9e184a4e80774e07212.tar.gz |
qcacld-3.0: Clear oldest cached sta information
Currently host is caching all the connected sta info
in case of SAP, once the sta count reaches to MAX, below
mentioned issues occurs:
1. Driver can not cache the information of newly connected
stations.
2. Some of the info is cached at the time of connection while
remaining info is cached during disconnection. In the
disconnect path driver tries to cache some of the info
such mc_bc count, disconnect reason code, since driver can't
cache anymore info, it does not find the current station which
is getting disconnected in cache sta info structure leading to
an error, and driver is returning an error without completing
the wait for disconnect event which is resulting in timeout.
Since sta_disconnect comes with rtnl_held, any other process
is not able to get the rtnl_lock until this timeout occurs.
To address this issue below mentioned two measures taken care:
Clear the oldest cached sta information and save the newly connected
station's information.
In the disconnect path, do not return any error and simply proceed
with disconnection as failure to cache the information of sta
should not stop the disconnection process.
Bug: 132884821
Bug: 133284357
Change-Id: Ia955a6774033fdfa91ff1fa7c8832b3ec7e8e1a0
CRs-Fixed: 2333075
Signed-off-by: hsuvictor <hsuvictor@google.com>
-rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 1 | ||||
-rw-r--r-- | core/hdd/src/wlan_hdd_hostapd.c | 73 |
2 files changed, 49 insertions, 25 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 8882266650..2c5e22d90f 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1046,6 +1046,7 @@ typedef struct { uint64_t rx_bytes; qdf_time_t last_tx_rx_ts; qdf_time_t assoc_ts; + qdf_time_t disassoc_ts; uint32_t tx_rate; uint32_t rx_rate; bool ampdu; diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 5730572166..9018e2323b 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1431,7 +1431,9 @@ static void hdd_fill_station_info(hdd_adapter_t *pHostapdAdapter, tSap_StationAssocReassocCompleteEvent *event) { hdd_station_info_t *stainfo; - uint8_t i = 0; + uint8_t i = 0, oldest_disassoc_sta_idx = WLAN_MAX_STA_COUNT + 1; + qdf_time_t oldest_disassoc_sta_ts = 0; + if (event->staId >= WLAN_MAX_STA_COUNT) { hdd_err("invalid sta id"); @@ -1491,8 +1493,6 @@ static void hdd_fill_station_info(hdd_adapter_t *pHostapdAdapter, cache_sta_info[i].macAddrSTA.bytes, event->staMac.bytes, QDF_MAC_ADDR_SIZE)) { - qdf_mem_zero(&pHostapdAdapter->cache_sta_info[i], - sizeof(*stainfo)); break; } i++; @@ -1503,14 +1503,36 @@ static void hdd_fill_station_info(hdd_adapter_t *pHostapdAdapter, while (i < WLAN_MAX_STA_COUNT) { if (pHostapdAdapter->cache_sta_info[i].isUsed != TRUE) break; + + if (pHostapdAdapter-> + cache_sta_info[i].disassoc_ts && + (!oldest_disassoc_sta_ts || + (qdf_system_time_after( + oldest_disassoc_sta_ts, + pHostapdAdapter-> + cache_sta_info[i].disassoc_ts)))) { + oldest_disassoc_sta_ts = + pHostapdAdapter-> + cache_sta_info[i].disassoc_ts; + oldest_disassoc_sta_idx = i; + } i++; } } - if (i < WLAN_MAX_STA_COUNT) + + if ((i == WLAN_MAX_STA_COUNT) && oldest_disassoc_sta_ts) { + hdd_debug("reached max cached staid, removing oldest stainfo"); + i = oldest_disassoc_sta_idx; + } + if (i < WLAN_MAX_STA_COUNT) { + qdf_mem_zero(&pHostapdAdapter->cache_sta_info[i], + sizeof(*stainfo)); qdf_mem_copy(&pHostapdAdapter->cache_sta_info[i], - stainfo, sizeof(hdd_station_info_t)); - else + stainfo, sizeof(hdd_station_info_t)); + + } else { hdd_debug("reached max staid, stainfo can't be cached"); + } hdd_debug("cap %d %d %d %d %d %d %d %d %d %x %d", stainfo->ampdu, @@ -1642,7 +1664,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, eCsrPhyMode phy_mode; bool legacy_phymode; tSap_StationDisassocCompleteEvent *disassoc_comp; - hdd_station_info_t *stainfo; + hdd_station_info_t *stainfo, *cache_stainfo; cds_context_type *cds_ctx; hdd_adapter_t *sta_adapter; @@ -2255,21 +2277,19 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, memcpy(wrqu.addr.sa_data, &disassoc_comp->staMac, QDF_MAC_ADDR_SIZE); - stainfo = hdd_get_stainfo(pHostapdAdapter->cache_sta_info, + cache_stainfo = hdd_get_stainfo(pHostapdAdapter->cache_sta_info, disassoc_comp->staMac); - if (!stainfo) { - hdd_err("peer " MAC_ADDRESS_STR " not found", - MAC_ADDR_ARRAY(wrqu.addr.sa_data)); - return -EINVAL; + if (cache_stainfo) { + /* Cache the disassoc info */ + cache_stainfo->rssi = disassoc_comp->rssi; + cache_stainfo->tx_rate = disassoc_comp->tx_rate; + cache_stainfo->rx_rate = disassoc_comp->rx_rate; + cache_stainfo->reason_code = disassoc_comp->reason_code; + cache_stainfo->disassoc_ts = qdf_system_ticks(); } hdd_notice(" disassociated " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(wrqu.addr.sa_data)); - stainfo->rssi = disassoc_comp->rssi; - stainfo->tx_rate = disassoc_comp->tx_rate; - stainfo->rx_rate = disassoc_comp->rx_rate; - stainfo->reason_code = disassoc_comp->reason_code; - qdf_status = qdf_event_set(&pHostapdState->qdf_sta_disassoc_event); if (!QDF_IS_STATUS_SUCCESS(qdf_status)) hdd_err("Station Deauth event Set failed"); @@ -2294,14 +2314,17 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, pHostapdAdapter->sessionId, QDF_PROTO_TYPE_MGMT, QDF_PROTO_MGMT_DISASSOC)); - /* Send DHCP STOP indication to FW */ - stainfo->dhcp_phase = DHCP_PHASE_ACK; - if (stainfo->dhcp_nego_status == - DHCP_NEGO_IN_PROGRESS) - hdd_post_dhcp_ind(pHostapdAdapter, staId, - WMA_DHCP_STOP_IND); - stainfo->dhcp_nego_status = DHCP_NEGO_STOP; - + stainfo = hdd_get_stainfo(pHostapdAdapter->aStaInfo, + disassoc_comp->staMac); + if (stainfo) { + /* Send DHCP STOP indication to FW */ + stainfo->dhcp_phase = DHCP_PHASE_ACK; + if (stainfo->dhcp_nego_status == + DHCP_NEGO_IN_PROGRESS) + hdd_post_dhcp_ind(pHostapdAdapter, staId, + WMA_DHCP_STOP_IND); + stainfo->dhcp_nego_status = DHCP_NEGO_STOP; + } hdd_softap_deregister_sta(pHostapdAdapter, staId); pHddApCtx->bApActive = false; |