From 24f86413a4d1faec051b9a44d0a476c9f031616b Mon Sep 17 00:00:00 2001 From: phadiman Date: Tue, 4 Aug 2020 12:47:29 +0530 Subject: [PATCH] qca-wifi: Access wlanstats context using CDP API Peer wlanstats context was accessed directly without any protection, if peer was deleted there was no way to know if PPDU cookie holds correct wlanstats ctx Hence to protect the peer wlanstats ctx access it using CDP API using stats context protection CRs-Fixed: 2740231 Change-Id: I9b07970c691099f3c9b0175d550508b50db9ac8a --- dp/inc/dp_rate_stats.h | 9 ++++ dp/src/dp_rate_stats.c | 110 ++++++++++++++++++++++++++++++++++------- 2 files changed, 102 insertions(+), 17 deletions(-) diff --git a/dp/inc/dp_rate_stats.h b/dp/inc/dp_rate_stats.h index 5a066c406e..35271fbcee 100644 --- a/dp/inc/dp_rate_stats.h +++ b/dp/inc/dp_rate_stats.h @@ -41,6 +41,11 @@ #define RATE_STATS_LOCK_ACQUIRE(lock) qdf_spin_lock_bh(lock) #define RATE_STATS_LOCK_RELEASE(lock) qdf_spin_unlock_bh(lock) +#define STATS_CTX_LOCK_CREATE(lock) qdf_spinlock_create(lock) +#define STATS_CTX_LOCK_DESTROY(lock) qdf_spinlock_destroy(lock) +#define STATS_CTX_LOCK_ACQUIRE(lock) qdf_spin_lock_bh(lock) +#define STATS_CTX_LOCK_RELEASE(lock) qdf_spin_unlock_bh(lock) + struct cdp_pdev; /** @@ -168,6 +173,8 @@ enum rdk_stats_version { * @rxs_cache_miss: rate index recevied is not in cache database * @stats_ver: peer statistics version * @is_lithium: is lithium or legacy + * @tx_ctx_lock: tx context soc level lock + * @rx_ctx_lock: rx context soc level lock */ struct wlan_soc_rate_stats_ctx { struct cdp_soc_t *soc; @@ -181,6 +188,8 @@ struct wlan_soc_rate_stats_ctx { uint32_t rxs_cache_miss; enum rdk_stats_version stats_ver; bool is_lithium; + qdf_spinlock_t tx_ctx_lock; + qdf_spinlock_t rx_ctx_lock; }; /** diff --git a/dp/src/dp_rate_stats.c b/dp/src/dp_rate_stats.c index d1485288f6..089e026478 100644 --- a/dp/src/dp_rate_stats.c +++ b/dp/src/dp_rate_stats.c @@ -64,6 +64,7 @@ wlan_peer_flush_rx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, if (!soc_stats_ctx) return; + rx_stats = &stats_ctx->rate_stats->rx; buf.cookie = 0; @@ -118,11 +119,23 @@ wlan_peer_flush_tx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, return; tx_stats = &stats_ctx->rate_stats->tx; + + buf.cookie = 0; buf.stats = (struct wlan_tx_rate_stats *)tx_stats->stats; buf.buf_len = (WLANSTATS_CACHE_SIZE * sizeof(struct wlan_tx_rate_stats) + sizeof(struct wlan_tx_sojourn_stats)); buf.stats_type = DP_PEER_TX_RATE_STATS; - buf.cookie = stats_ctx->peer_cookie; + /* Prepare 64 bit cookie */ + /*-------------------|-------------------| + * 32 bit target | 32 bit peer cookie| + *-------------------|-------------------| + */ + buf.cookie = ((((buf.cookie | soc_stats_ctx->is_lithium) + << WLANSTATS_PEER_COOKIE_LSB) & + WLANSTATS_COOKIE_PLATFORM_OFFSET) | + (((buf.cookie | stats_ctx->peer_cookie) & + WLANSTATS_COOKIE_PEER_COOKIE_OFFSET))); + wlan_peer_read_sojourn_average(tx_stats); qdf_mem_copy(buf.peer_mac, stats_ctx->mac_addr, WLAN_MAC_ADDR_LEN); cdp_peer_flush_rate_stats(soc_stats_ctx->soc, @@ -157,10 +170,20 @@ wlan_peer_flush_tx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, tx_stats = &stats_ctx->link_metrics->tx; + buf.cookie = 0; buf.stats = (struct wlan_tx_link_stats *)&tx_stats->stats; buf.buf_len = sizeof(struct wlan_peer_tx_link_stats); buf.stats_type = DP_PEER_TX_LINK_STATS; - buf.cookie = stats_ctx->peer_cookie; + /* Prepare 64 bit cookie */ + /*-------------------|-------------------| + * 32 bit target | 32 bit peer cookie| + *-------------------|-------------------| + */ + buf.cookie = ((((buf.cookie | soc_stats_ctx->is_lithium) + << WLANSTATS_PEER_COOKIE_LSB) & + WLANSTATS_COOKIE_PLATFORM_OFFSET) | + (((buf.cookie | stats_ctx->peer_cookie) & + WLANSTATS_COOKIE_PEER_COOKIE_OFFSET))); tx_stats->stats.ack_rssi.internal = qdf_ewma_rx_rssi_read(&tx_stats->stats.ack_rssi); @@ -205,10 +228,20 @@ wlan_peer_flush_rx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, rx_stats = &stats_ctx->link_metrics->rx; + buf.cookie = 0; buf.stats = (struct wlan_rx_link_stats *)&rx_stats->stats; buf.buf_len = sizeof(struct wlan_peer_rx_link_stats); buf.stats_type = DP_PEER_RX_LINK_STATS; - buf.cookie = stats_ctx->peer_cookie; + /* Prepare 64 bit cookie */ + /*-------------------|-------------------| + * 32 bit target | 32 bit peer cookie| + *-------------------|-------------------| + */ + buf.cookie = ((((buf.cookie | soc_stats_ctx->is_lithium) + << WLANSTATS_PEER_COOKIE_LSB) & + WLANSTATS_COOKIE_PLATFORM_OFFSET) | + (((buf.cookie | stats_ctx->peer_cookie) & + WLANSTATS_COOKIE_PEER_COOKIE_OFFSET))); rx_stats->stats.su_rssi.internal = qdf_ewma_rx_rssi_read(&rx_stats->stats.su_rssi); @@ -334,13 +367,16 @@ wlan_peer_update_tx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, for (user_idx = 0; user_idx < cdp_tx_ppdu->num_users; user_idx++) { ppdu_user = &cdp_tx_ppdu->user[user_idx]; - stats_ctx = (struct wlan_peer_rate_stats_ctx *) - ppdu_user->cookie; + STATS_CTX_LOCK_ACQUIRE(&soc_stats_ctx->tx_ctx_lock); + stats_ctx = cdp_peer_get_wlanstats_ctx(soc_stats_ctx->soc, + cdp_tx_ppdu->vdev_id, + ppdu_user->mac_addr); if (qdf_unlikely(!stats_ctx)) { qdf_warn("peer rate stats ctx is NULL, return"); qdf_warn("peer_mac: " QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(stats_ctx->mac_addr)); + QDF_MAC_ADDR_ARRAY(ppdu_user->mac_addr)); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock); continue; } @@ -383,6 +419,7 @@ wlan_peer_update_tx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, ppdu_user->usr_ack_rssi); RATE_STATS_LOCK_RELEASE(&stats_ctx->link_metrics->tx.lock); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock); } } @@ -399,16 +436,21 @@ wlan_peer_update_rx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, soc_stats_ctx->stats_ver != RDK_ALL_STATS) return; - for (user_idx = 0; user_idx < cdp_rx_ppdu->num_users; user_idx++) { + for (user_idx = 0; + user_idx < cdp_rx_ppdu->num_users && user_idx < CDP_MU_MAX_USERS; + user_idx++) { ppdu_user = &cdp_rx_ppdu->user[user_idx]; - stats_ctx = (struct wlan_peer_rate_stats_ctx *) - ppdu_user->cookie; + STATS_CTX_LOCK_ACQUIRE(&soc_stats_ctx->rx_ctx_lock); + stats_ctx = cdp_peer_get_wlanstats_ctx(soc_stats_ctx->soc, + ppdu_user->vdev_id, + ppdu_user->mac_addr); if (qdf_unlikely(!stats_ctx)) { qdf_warn("peer rate stats ctx is NULL, return"); qdf_warn("peer_mac: " QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(stats_ctx->mac_addr)); + QDF_MAC_ADDR_ARRAY(ppdu_user->mac_addr)); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock); continue; } @@ -450,6 +492,7 @@ wlan_peer_update_rx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, } RATE_STATS_LOCK_RELEASE(&stats_ctx->link_metrics->rx.lock); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock); } } @@ -469,15 +512,28 @@ wlan_peer_update_rx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, soc_stats_ctx->stats_ver != RDK_ALL_STATS) return; - for (user_idx = 0; user_idx < cdp_rx_ppdu->num_users; user_idx++) { - ppdu_user = &cdp_rx_ppdu->user[user_idx]; - stats_ctx = (struct wlan_peer_rate_stats_ctx *) - ppdu_user->cookie; + user_idx = 0; + do { + STATS_CTX_LOCK_ACQUIRE(&soc_stats_ctx->rx_ctx_lock); + if (cdp_rx_ppdu->u.ppdu_type != DP_PPDU_TYPE_SU) { + ppdu_user = &cdp_rx_ppdu->user[user_idx]; + + stats_ctx = + cdp_peer_get_wlanstats_ctx(soc_stats_ctx->soc, + ppdu_user->vdev_id, + ppdu_user->mac_addr); + } else { + stats_ctx = + cdp_peer_get_wlanstats_ctx(soc_stats_ctx->soc, + cdp_rx_ppdu->vdev_id, + cdp_rx_ppdu->mac_addr); + } if (qdf_unlikely(!stats_ctx)) { qdf_warn("peer rate stats ctx is NULL, return"); qdf_warn("peer_mac: " QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(cdp_rx_ppdu->mac_addr)); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock); continue; } @@ -485,6 +541,7 @@ wlan_peer_update_rx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, if (qdf_unlikely(!cdp_rx_ppdu->rx_ratekbps || cdp_rx_ppdu->rix > DP_RATE_TABLE_SIZE)) { + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock); return; } @@ -495,6 +552,8 @@ wlan_peer_update_rx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, cdp_rx_ppdu); soc_stats_ctx->rxs_last_idx_cache_hit++; RATE_STATS_LOCK_RELEASE(&rx_stats->lock); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock); + user_idx++; continue; } @@ -518,6 +577,8 @@ wlan_peer_update_rx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, rx_stats->cur_cache_idx = cache_idx; soc_stats_ctx->rxs_cache_hit++; RATE_STATS_LOCK_RELEASE(&rx_stats->lock); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock); + user_idx++; continue; } else { wlan_peer_flush_rx_rate_stats(soc_stats_ctx, stats_ctx); @@ -529,7 +590,11 @@ wlan_peer_update_rx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, soc_stats_ctx->rxs_cache_miss++; } RATE_STATS_LOCK_RELEASE(&rx_stats->lock); - } + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock); + + user_idx++; + } while (user_idx < cdp_rx_ppdu->num_users && + user_idx < CDP_MU_MAX_USERS); } static inline void @@ -579,11 +644,15 @@ wlan_peer_update_tx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, for (user_idx = 0; user_idx < cdp_tx_ppdu->num_users; user_idx++) { ppdu_user = &cdp_tx_ppdu->user[user_idx]; - stats_ctx = (struct wlan_peer_rate_stats_ctx *) - ppdu_user->cookie; + + STATS_CTX_LOCK_ACQUIRE(&soc_stats_ctx->tx_ctx_lock); + stats_ctx = cdp_peer_get_wlanstats_ctx(soc_stats_ctx->soc, + cdp_tx_ppdu->vdev_id, + ppdu_user->mac_addr); if (qdf_unlikely(!ppdu_user->tx_ratekbps || !ppdu_user->rix || ppdu_user->rix > DP_RATE_TABLE_SIZE)) { + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock); continue; } @@ -591,6 +660,7 @@ wlan_peer_update_tx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, qdf_debug("peer rate stats ctx is NULL, investigate"); qdf_debug("peer_mac: " QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(ppdu_user->mac_addr)); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock); continue; } @@ -602,6 +672,7 @@ wlan_peer_update_tx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, __wlan_peer_update_tx_rate_stats(__tx_stats, ppdu_user); soc_stats_ctx->txs_last_idx_cache_hit++; RATE_STATS_LOCK_RELEASE(&tx_stats->lock); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock); continue; } @@ -638,6 +709,7 @@ wlan_peer_update_tx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx, tx_stats->cur_cache_idx = 0; } RATE_STATS_LOCK_RELEASE(&tx_stats->lock); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock); } } @@ -804,6 +876,8 @@ void wlan_peer_destroy_event_handler(void *ctx, enum WDI_EVENT event, peer_info = (struct cdp_peer_cookie *)buf; stats = (struct wlan_peer_rate_stats_ctx *)peer_info->ctx; + STATS_CTX_LOCK_ACQUIRE(&soc_stats_ctx->tx_ctx_lock); + STATS_CTX_LOCK_ACQUIRE(&soc_stats_ctx->rx_ctx_lock); if (stats) { wlan_peer_flush_rate_stats(ctx, stats); if (stats->rate_stats) { @@ -819,5 +893,7 @@ void wlan_peer_destroy_event_handler(void *ctx, enum WDI_EVENT event, qdf_mem_free(stats); qdf_info("DEBUG DEiniitialized rate stats"); } + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock); + STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock); } #endif