summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshish Kumar Dhanotiya <adhanoti@codeaurora.org>2018-10-12 21:13:57 +0530
committerVictor Hsu <hsuvictor@google.com>2019-05-24 07:21:44 +0000
commit568347358ef99e8b8946d9e184a4e80774e07212 (patch)
tree0748aa528004b09668aab74d9f646af78bc79e18
parent0371413c87b552b7d93df37ac169dfb4d1b1fe6a (diff)
downloadqcacld-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.h1
-rw-r--r--core/hdd/src/wlan_hdd_hostapd.c73
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;