Merge changes into win_wlan_host.1.0
diff --git a/dp/inc/dp_rate_stats.h b/dp/inc/dp_rate_stats.h
index b840c57..35271fb 100644
--- a/dp/inc/dp_rate_stats.h
+++ b/dp/inc/dp_rate_stats.h
@@ -41,9 +41,28 @@
#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;
/**
+ * enum dp_ppdu_type - enum for ppdu_type
+ * @DP_PPDU_TYPE_SU: single user PPDU
+ * @DP_PPDU_TYPE_MU_MIMO: multi user mimo ppdu
+ * @DP_PPDU_TYPE_MU_OFDMA: multi user ofdma ppdu
+ * @DP_PPDU_TYPE_MU_OFDMA_MIMO: multi user mimo/ofdma ppdu
+ */
+enum dp_ppdu_type {
+ DP_PPDU_TYPE_SU,
+ DP_PPDU_TYPE_MU_MIMO,
+ DP_PPDU_TYPE_MU_OFDMA,
+ DP_PPDU_TYPE_MU_OFDMA_MIMO,
+};
+
+/**
* struct wlan_peer_tx_rate_stats - peer tx rate statistics
* @stats: array containing tx rate stats
* @cur_rix: rate index updated last in list
@@ -72,22 +91,76 @@
};
/**
- * struct wlan_peer_rate_stats - Peer rate statistics ctx
+ * struct wlan_peer_rx_link_stats - Peer Rx Link statistics
+ * @stats: array containing rx rate stats
+ * @lock: lock protecting list
+ */
+struct wlan_peer_rx_link_stats {
+ struct wlan_rx_link_stats stats;
+ qdf_spinlock_t lock;
+};
+
+/**
+ * struct wlan_peer_tx_link_stats - Peer Tx Link statistics
+ * @stats: array containing rx rate stats
+ * @lock: lock protecting list
+ */
+struct wlan_peer_tx_link_stats {
+ struct wlan_tx_link_stats stats;
+ qdf_spinlock_t lock;
+};
+
+/**
+ * struct wlan_peer_rate_stats - Rate statistics
* @tx: tx rate statistics
* @rx: rx rate statistics
+ */
+struct wlan_peer_rate_stats {
+ struct wlan_peer_tx_rate_stats tx;
+ struct wlan_peer_rx_rate_stats rx;
+};
+
+/**
+ * struct wlan_peer_link_metrics - Peer link metrics
+ * @tx: tx link quality stats
+ * @rx: rx link quality stats
+ */
+struct wlan_peer_link_metrics {
+ struct wlan_peer_tx_link_stats tx;
+ struct wlan_peer_rx_link_stats rx;
+};
+
+/**
+ * struct wlan_peer_rate_stats_ctx - Peer statistics context
+ * @rate_stats: Rate statistics (version 1 stats)
+ * @link_metrics: Link Metrics (version 2 stats)
* @mac_addr: peer MAC address
* @peer_cookie: cookie for unique session of peer
* @pdev_id: id of dp pdev
*/
struct wlan_peer_rate_stats_ctx {
- struct wlan_peer_tx_rate_stats tx;
- struct wlan_peer_rx_rate_stats rx;
+ struct wlan_peer_rate_stats *rate_stats;
+ struct wlan_peer_link_metrics *link_metrics;
uint8_t mac_addr[WLAN_MAC_ADDR_LEN];
uint64_t peer_cookie;
uint8_t pdev_id;
};
/**
+ * enum rdk_stats_version - Peer statistics versions
+ * @RDK_STATS_DISABLED: peer statistics disabled
+ * @RDK_RATE_STATS: peer rate statistics enabled
+ * @RDK_LINK_STATS: peer link metrics enabled
+ * @RDK_ALL_STATS: peer all statistics enabled
+ */
+enum rdk_stats_version {
+ RDK_STATS_DISABLED = 0,
+ RDK_RATE_STATS = 1,
+ RDK_LINK_STATS = 2,
+ RDK_ALL_STATS = 3,
+};
+
+/**
* struct wlan_soc_rate_stats_ctx - rate stats context at soc level
* @soc: Opaque soc handle
* @txs_cache_flush: tx stats flush count
@@ -98,6 +171,10 @@
* @rxs_cache_hit: cache hit for rate index received from cache database
* @txs_cache_miss: rate index recevied is not in cache database
* @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;
@@ -109,7 +186,10 @@
uint32_t rxs_cache_hit;
uint32_t txs_cache_miss;
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/inc/dp_rate_stats_pub.h b/dp/inc/dp_rate_stats_pub.h
index 1d1ea74..aa219b0 100644
--- a/dp/inc/dp_rate_stats_pub.h
+++ b/dp/inc/dp_rate_stats_pub.h
@@ -84,6 +84,8 @@
DP_PEER_RX_RATE_STATS,
DP_PEER_TX_RATE_STATS,
DP_PEER_SOJOURN_STATS,
+ DP_PEER_RX_LINK_STATS,
+ DP_PEER_TX_LINK_STATS,
};
/** struct wlan_tx_rate_stats - Tx packet rate info
@@ -146,6 +148,86 @@
qdf_ewma_tx_lag avg_sojourn_msdu[WLAN_DATA_TID_MAX];
};
+#define BW_USAGE_MAX_SIZE 4
+
+/**
+ * struct wlan_peer_bw_stats - per link bw related stats
+ * @usage_total - sum of total BW (20, 40, 80, 160)
+ * @usage_avg - @usage_total / number of PPDUs (avg BW)
+ * @usage_counter - each BW usage counter
+ * @usage_max - number of pkts in max BW mode
+ */
+struct wlan_peer_bw_stats {
+ uint32_t usage_total;
+ uint32_t usage_counter[BW_USAGE_MAX_SIZE];
+ uint8_t usage_avg;
+ uint8_t usage_max;
+};
+
+/**
+ * struct wlan_rx_link_stats - Peer Rx link statistics
+ * @num_ppdus - number of ppdus per user
+ * @bytes - number of bytes per user
+ * @phy_rate_lpf_avg_su - SU packet LPF averaged rx rate
+ * @phy_rate_actual_su - SU packet rounded average rx rate
+ * @phy_rate_lpf_avg_mu - MU packet LPF averaged rx rate
+ * @phy_rate_actual_mu - MUpacket rounded average rx rate
+ * @ofdma_usage - number of packet in OFDMA
+ * @mu_mimo_usage - number of pakcets in MU MIMO
+ * @bw - average BW and max BW related structure
+ * @su_rssi - single user RSSI
+ * @mpdu_retries - number of retried MPDUs
+ * @pkt_error_rate - average packet error rate
+ * @num_mpdus - total number of mpdus
+ */
+struct wlan_rx_link_stats {
+ uint64_t bytes;
+ uint32_t num_ppdus;
+ uint32_t phy_rate_lpf_avg_su;
+ uint32_t phy_rate_actual_su;
+ uint32_t phy_rate_lpf_avg_mu;
+ uint32_t phy_rate_actual_mu;
+ uint32_t ofdma_usage;
+ uint32_t mu_mimo_usage;
+ struct wlan_peer_bw_stats bw;
+ qdf_ewma_rx_rssi su_rssi;
+ uint32_t mpdu_retries;
+ uint32_t num_mpdus;
+ uint8_t pkt_error_rate;
+};
+
+/**
+ * struct wlan_tx_link_stats - Peer tx link statistics
+ * @num_ppdus - number of ppdus per user
+ * @bytes - number of bytes per user
+ * @phy_rate_lpf_avg_su - SU packet LPF averaged tx rate
+ * @phy_rate_actual_su - SU packet rounded average tx rate
+ * @phy_rate_lpf_avg_mu - MU packet LPF averaged tx rate
+ * @phy_rate_actual_mu - MUpacket rounded average tx rate
+ * @ofdma_usage - number of packet in OFDMA
+ * @mu_mimo_usage - number of pakcets in MU MIMO
+ * @bw - average BW and max BW related structure
+ * @ack_rssi - averaged ACK rssi
+ * @mpdu_failed - number of failed MPDUs
+ * @mpdu_success - number of success MPDUs
+ * @pkt_error_rate - average packet error rate
+ */
+struct wlan_tx_link_stats {
+ uint64_t bytes;
+ uint32_t num_ppdus;
+ uint32_t phy_rate_lpf_avg_su;
+ uint32_t phy_rate_actual_su;
+ uint32_t phy_rate_lpf_avg_mu;
+ uint32_t phy_rate_actual_mu;
+ uint32_t ofdma_usage;
+ uint32_t mu_mimo_usage;
+ struct wlan_peer_bw_stats bw;
+ qdf_ewma_rx_rssi ack_rssi;
+ uint32_t mpdu_failed;
+ uint32_t mpdu_success;
+ uint8_t pkt_error_rate;
+};
+
/**
* struct wlan_peer_rate_stats_intf - Interface structure to
* flush stats to user spave entity
diff --git a/dp/src/dp_rate_stats.c b/dp/src/dp_rate_stats.c
index 1bd4e84..089e026 100644
--- a/dp/src/dp_rate_stats.c
+++ b/dp/src/dp_rate_stats.c
@@ -26,6 +26,14 @@
#ifdef QCA_SUPPORT_RDK_STATS
+/* Calculate actual BW from BW ENUM as in
+ * x = 0 for 20MHz
+ * x = 1 for 40MHz
+ * x = 2 for 80MHz
+ * x = 3 for 160MHz
+ */
+#define GET_BW_FROM_BW_ENUM(x) ((20) * (1 << x))
+
static void
wlan_peer_read_ewma_avg_rssi(struct wlan_rx_rate_stats *rx_stats)
{
@@ -56,7 +64,8 @@
if (!soc_stats_ctx)
return;
- rx_stats = &stats_ctx->rx;
+
+ rx_stats = &stats_ctx->rate_stats->rx;
buf.cookie = 0;
wlan_peer_read_ewma_avg_rssi(rx_stats->stats);
@@ -109,12 +118,24 @@
if (!soc_stats_ctx)
return;
- tx_stats = &stats_ctx->tx;
+ 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,
@@ -135,22 +156,156 @@
}
static void
+wlan_peer_flush_tx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx,
+ struct wlan_peer_rate_stats_ctx *stats_ctx)
+{
+ struct wlan_peer_rate_stats_intf buf;
+ struct wlan_peer_tx_link_stats *tx_stats;
+ uint8_t bw_max_idx;
+
+ if (!soc_stats_ctx) {
+ qdf_info("soc stats context is NULL\n");
+ return;
+ }
+
+ 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;
+ /* 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);
+ tx_stats->stats.phy_rate_actual_su =
+ dp_ath_rate_out(tx_stats->stats.phy_rate_lpf_avg_su);
+ tx_stats->stats.phy_rate_actual_mu =
+ dp_ath_rate_out(tx_stats->stats.phy_rate_lpf_avg_mu);
+
+ if (tx_stats->stats.num_ppdus) {
+ tx_stats->stats.bw.usage_avg = tx_stats->stats.bw.usage_total /
+ tx_stats->stats.num_ppdus;
+ bw_max_idx = tx_stats->stats.bw.usage_max;
+ tx_stats->stats.bw.usage_max =
+ (tx_stats->stats.bw.usage_counter[bw_max_idx] * 100) /
+ tx_stats->stats.num_ppdus;
+ }
+
+ if (tx_stats->stats.mpdu_success)
+ tx_stats->stats.pkt_error_rate =
+ (tx_stats->stats.mpdu_failed * 100) /
+ tx_stats->stats.mpdu_success;
+
+ qdf_mem_copy(buf.peer_mac, stats_ctx->mac_addr, WLAN_MAC_ADDR_LEN);
+ cdp_peer_flush_rate_stats(soc_stats_ctx->soc,
+ stats_ctx->pdev_id, &buf);
+
+ qdf_mem_zero(&tx_stats->stats, sizeof(struct wlan_tx_link_stats));
+}
+
+static void
+wlan_peer_flush_rx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx,
+ struct wlan_peer_rate_stats_ctx *stats_ctx)
+{
+ struct wlan_peer_rate_stats_intf buf;
+ struct wlan_peer_rx_link_stats *rx_stats;
+ uint8_t bw_max_idx;
+
+ if (!soc_stats_ctx) {
+ qdf_info("soc stats context is NULL\n");
+ return;
+ }
+
+ 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;
+ /* 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);
+ rx_stats->stats.phy_rate_actual_su =
+ dp_ath_rate_out(rx_stats->stats.phy_rate_lpf_avg_su);
+ rx_stats->stats.phy_rate_actual_mu =
+ dp_ath_rate_out(rx_stats->stats.phy_rate_lpf_avg_mu);
+ if (rx_stats->stats.num_ppdus) {
+ rx_stats->stats.bw.usage_avg = rx_stats->stats.bw.usage_total /
+ rx_stats->stats.num_ppdus;
+ bw_max_idx = rx_stats->stats.bw.usage_max;
+ rx_stats->stats.bw.usage_max =
+ (rx_stats->stats.bw.usage_counter[bw_max_idx] * 100) /
+ rx_stats->stats.num_ppdus;
+ }
+
+ if (rx_stats->stats.num_mpdus)
+ rx_stats->stats.pkt_error_rate =
+ (rx_stats->stats.mpdu_retries * 100) /
+ rx_stats->stats.num_mpdus;
+
+ qdf_mem_copy(buf.peer_mac, stats_ctx->mac_addr, WLAN_MAC_ADDR_LEN);
+ cdp_peer_flush_rate_stats(soc_stats_ctx->soc,
+ stats_ctx->pdev_id, &buf);
+
+ qdf_mem_zero(&rx_stats->stats, sizeof(struct wlan_rx_link_stats));
+}
+
+static void
wlan_peer_flush_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx,
struct wlan_peer_rate_stats_ctx *stats_ctx)
{
struct wlan_peer_tx_rate_stats *tx_stats;
struct wlan_peer_rx_rate_stats *rx_stats;
+ struct wlan_peer_tx_link_stats *tx_link_stats;
+ struct wlan_peer_rx_link_stats *rx_link_stats;
- tx_stats = &stats_ctx->tx;
- rx_stats = &stats_ctx->rx;
+ if (soc_stats_ctx->stats_ver == RDK_RATE_STATS ||
+ soc_stats_ctx->stats_ver == RDK_ALL_STATS) {
+ tx_stats = &stats_ctx->rate_stats->tx;
+ rx_stats = &stats_ctx->rate_stats->rx;
- RATE_STATS_LOCK_ACQUIRE(&tx_stats->lock);
- wlan_peer_flush_tx_rate_stats(soc_stats_ctx, stats_ctx);
- RATE_STATS_LOCK_RELEASE(&tx_stats->lock);
+ RATE_STATS_LOCK_ACQUIRE(&tx_stats->lock);
+ wlan_peer_flush_tx_rate_stats(soc_stats_ctx, stats_ctx);
+ RATE_STATS_LOCK_RELEASE(&tx_stats->lock);
- RATE_STATS_LOCK_ACQUIRE(&rx_stats->lock);
- wlan_peer_flush_rx_rate_stats(soc_stats_ctx, stats_ctx);
- RATE_STATS_LOCK_RELEASE(&rx_stats->lock);
+ RATE_STATS_LOCK_ACQUIRE(&rx_stats->lock);
+ wlan_peer_flush_rx_rate_stats(soc_stats_ctx, stats_ctx);
+ RATE_STATS_LOCK_RELEASE(&rx_stats->lock);
+ }
+
+ if (soc_stats_ctx->stats_ver == RDK_LINK_STATS ||
+ soc_stats_ctx->stats_ver == RDK_ALL_STATS) {
+ tx_link_stats = &stats_ctx->link_metrics->tx;
+ rx_link_stats = &stats_ctx->link_metrics->rx;
+
+ RATE_STATS_LOCK_ACQUIRE(&tx_link_stats->lock);
+ wlan_peer_flush_tx_link_stats(soc_stats_ctx, stats_ctx);
+ RATE_STATS_LOCK_RELEASE(&tx_link_stats->lock);
+
+ RATE_STATS_LOCK_ACQUIRE(&rx_link_stats->lock);
+ wlan_peer_flush_rx_link_stats(soc_stats_ctx, stats_ctx);
+ RATE_STATS_LOCK_RELEASE(&rx_link_stats->lock);
+ }
}
void wlan_peer_rate_stats_flush_req(void *ctx, enum WDI_EVENT event,
@@ -197,71 +352,249 @@
}
static void
+wlan_peer_update_tx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx,
+ struct cdp_tx_completion_ppdu *cdp_tx_ppdu)
+{
+ struct cdp_tx_completion_ppdu_user *ppdu_user;
+ struct wlan_peer_rate_stats_ctx *stats_ctx;
+ struct wlan_tx_link_stats *tx_stats;
+ uint8_t user_idx;
+
+ if (soc_stats_ctx->stats_ver != RDK_LINK_STATS &&
+ soc_stats_ctx->stats_ver != RDK_ALL_STATS)
+ return;
+
+ for (user_idx = 0; user_idx < cdp_tx_ppdu->num_users; user_idx++) {
+ ppdu_user = &cdp_tx_ppdu->user[user_idx];
+
+ 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(ppdu_user->mac_addr));
+ STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock);
+ continue;
+ }
+
+ tx_stats = &stats_ctx->link_metrics->tx.stats;
+
+ RATE_STATS_LOCK_ACQUIRE(&stats_ctx->link_metrics->tx.lock);
+
+ tx_stats->num_ppdus += ppdu_user->long_retries + 1;
+ tx_stats->bytes += ppdu_user->success_bytes;
+ tx_stats->mpdu_failed += ppdu_user->mpdu_failed;
+ tx_stats->mpdu_success += ppdu_user->mpdu_success;
+
+ if (ppdu_user->ppdu_type == DP_PPDU_TYPE_SU) {
+ tx_stats->phy_rate_lpf_avg_su =
+ dp_ath_rate_lpf(tx_stats->phy_rate_lpf_avg_su,
+ ppdu_user->tx_ratekbps);
+ } else if (ppdu_user->ppdu_type == DP_PPDU_TYPE_MU_OFDMA ||
+ ppdu_user->ppdu_type == DP_PPDU_TYPE_MU_MIMO) {
+ tx_stats->phy_rate_lpf_avg_mu =
+ dp_ath_rate_lpf(tx_stats->phy_rate_lpf_avg_mu,
+ ppdu_user->tx_ratekbps);
+
+ if (ppdu_user->ppdu_type == DP_PPDU_TYPE_MU_OFDMA)
+ tx_stats->ofdma_usage++;
+
+ if (ppdu_user->ppdu_type == DP_PPDU_TYPE_MU_MIMO)
+ tx_stats->mu_mimo_usage++;
+ }
+
+ tx_stats->bw.usage_total += GET_BW_FROM_BW_ENUM(ppdu_user->bw);
+
+ if (ppdu_user->bw < BW_USAGE_MAX_SIZE) {
+ if (tx_stats->bw.usage_max < ppdu_user->bw)
+ tx_stats->bw.usage_max = ppdu_user->bw;
+ tx_stats->bw.usage_counter[ppdu_user->bw]++;
+ }
+
+ if (ppdu_user->ack_rssi_valid)
+ qdf_ewma_rx_rssi_add(&tx_stats->ack_rssi,
+ 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);
+ }
+}
+
+static void
+wlan_peer_update_rx_link_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx,
+ struct cdp_rx_indication_ppdu *cdp_rx_ppdu)
+{
+ struct cdp_rx_stats_ppdu_user *ppdu_user;
+ struct wlan_peer_rate_stats_ctx *stats_ctx;
+ struct wlan_rx_link_stats *rx_stats;
+ uint8_t user_idx;
+
+ if (soc_stats_ctx->stats_ver != RDK_LINK_STATS &&
+ soc_stats_ctx->stats_ver != RDK_ALL_STATS)
+ return;
+
+ 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_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(ppdu_user->mac_addr));
+ STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock);
+ continue;
+ }
+
+ rx_stats = &stats_ctx->link_metrics->rx.stats;
+
+ RATE_STATS_LOCK_ACQUIRE(&stats_ctx->link_metrics->rx.lock);
+
+ rx_stats->num_ppdus++;
+ rx_stats->bytes += cdp_rx_ppdu->num_bytes;
+ rx_stats->mpdu_retries += ppdu_user->retries;
+ rx_stats->num_mpdus += ppdu_user->mpdu_cnt_fcs_ok;
+
+ if (cdp_rx_ppdu->u.ppdu_type == DP_PPDU_TYPE_SU) {
+ rx_stats->phy_rate_lpf_avg_su =
+ dp_ath_rate_lpf(rx_stats->phy_rate_lpf_avg_su,
+ cdp_rx_ppdu->rx_ratekbps);
+ qdf_ewma_rx_rssi_add(&rx_stats->su_rssi,
+ cdp_rx_ppdu->rssi);
+ } else if (cdp_rx_ppdu->u.ppdu_type == DP_PPDU_TYPE_MU_OFDMA ||
+ cdp_rx_ppdu->u.ppdu_type == DP_PPDU_TYPE_MU_MIMO) {
+ rx_stats->phy_rate_lpf_avg_mu =
+ dp_ath_rate_lpf(rx_stats->phy_rate_lpf_avg_mu,
+ cdp_rx_ppdu->rx_ratekbps);
+
+ if (cdp_rx_ppdu->u.ppdu_type == DP_PPDU_TYPE_MU_OFDMA)
+ rx_stats->ofdma_usage++;
+
+ if (cdp_rx_ppdu->u.ppdu_type == DP_PPDU_TYPE_MU_MIMO)
+ rx_stats->mu_mimo_usage++;
+ }
+
+ rx_stats->bw.usage_total +=
+ GET_BW_FROM_BW_ENUM(cdp_rx_ppdu->u.bw);
+
+ if (cdp_rx_ppdu->u.bw < BW_USAGE_MAX_SIZE) {
+ if (rx_stats->bw.usage_max < cdp_rx_ppdu->u.bw)
+ rx_stats->bw.usage_max = cdp_rx_ppdu->u.bw;
+ rx_stats->bw.usage_counter[cdp_rx_ppdu->u.bw]++;
+ }
+
+ RATE_STATS_LOCK_RELEASE(&stats_ctx->link_metrics->rx.lock);
+ STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->rx_ctx_lock);
+ }
+}
+
+static void
wlan_peer_update_rx_rate_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx,
struct cdp_rx_indication_ppdu *cdp_rx_ppdu)
{
struct wlan_peer_rate_stats_ctx *stats_ctx;
struct wlan_peer_rx_rate_stats *rx_stats;
struct wlan_rx_rate_stats *__rx_stats;
+ struct cdp_rx_stats_ppdu_user *ppdu_user;
uint8_t cache_idx;
+ uint8_t user_idx;
bool idx_match = false;
- stats_ctx = (struct wlan_peer_rate_stats_ctx *)cdp_rx_ppdu->cookie;
-
- 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));
+ if (soc_stats_ctx->stats_ver != RDK_RATE_STATS &&
+ soc_stats_ctx->stats_ver != RDK_ALL_STATS)
return;
- }
- rx_stats = &stats_ctx->rx;
+ 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];
- if (qdf_unlikely(!cdp_rx_ppdu->rx_ratekbps ||
- cdp_rx_ppdu->rix > DP_RATE_TABLE_SIZE)) {
- return;
- }
-
- RATE_STATS_LOCK_ACQUIRE(&rx_stats->lock);
- if (qdf_likely(rx_stats->cur_rix == cdp_rx_ppdu->rix)) {
- __rx_stats = &rx_stats->stats[rx_stats->cur_cache_idx];
- __wlan_peer_update_rx_rate_stats(__rx_stats,
- cdp_rx_ppdu);
-
- soc_stats_ctx->rxs_last_idx_cache_hit++;
- goto done;
- }
-
- /* check if cache is available */
- for (cache_idx = 0; cache_idx < WLANSTATS_CACHE_SIZE; cache_idx++) {
- __rx_stats = &rx_stats->stats[cache_idx];
- if ((__rx_stats->rix == INVALID_CACHE_IDX) ||
- (__rx_stats->rix == cdp_rx_ppdu->rix)) {
- idx_match = true;
- break;
+ 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 index matches or found empty index, update stats to that
- * cache index else flush cache and update stats to cache index zero
- */
- if (idx_match) {
- __wlan_peer_update_rx_rate_stats(__rx_stats,
- cdp_rx_ppdu);
- rx_stats->cur_rix = cdp_rx_ppdu->rix;
- rx_stats->cur_cache_idx = cache_idx;
- soc_stats_ctx->rxs_cache_hit++;
- goto done;
- } else {
- wlan_peer_flush_rx_rate_stats(soc_stats_ctx, stats_ctx);
- __rx_stats = &rx_stats->stats[0];
- __wlan_peer_update_rx_rate_stats(__rx_stats,
- cdp_rx_ppdu);
- rx_stats->cur_rix = cdp_rx_ppdu->rix;
- rx_stats->cur_cache_idx = 0;
- soc_stats_ctx->rxs_cache_miss++;
- }
-done:
- RATE_STATS_LOCK_RELEASE(&rx_stats->lock);
+
+ 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;
+ }
+
+ rx_stats = &stats_ctx->rate_stats->rx;
+
+ 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;
+ }
+
+ RATE_STATS_LOCK_ACQUIRE(&rx_stats->lock);
+ if (qdf_likely(rx_stats->cur_rix == cdp_rx_ppdu->rix)) {
+ __rx_stats = &rx_stats->stats[rx_stats->cur_cache_idx];
+ __wlan_peer_update_rx_rate_stats(__rx_stats,
+ 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;
+ }
+
+ /* check if cache is available */
+ for (cache_idx = 0; cache_idx < WLANSTATS_CACHE_SIZE; cache_idx++) {
+ __rx_stats = &rx_stats->stats[cache_idx];
+ if ((__rx_stats->rix == INVALID_CACHE_IDX) ||
+ (__rx_stats->rix == cdp_rx_ppdu->rix)) {
+ idx_match = true;
+ break;
+ }
+ }
+ /* if index matches or found empty index, update stats to that
+ * cache index else flush cache and update stats to cache index
+ * zero
+ */
+ if (idx_match) {
+ __wlan_peer_update_rx_rate_stats(__rx_stats,
+ cdp_rx_ppdu);
+ rx_stats->cur_rix = cdp_rx_ppdu->rix;
+ 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);
+ __rx_stats = &rx_stats->stats[0];
+ __wlan_peer_update_rx_rate_stats(__rx_stats,
+ cdp_rx_ppdu);
+ rx_stats->cur_rix = cdp_rx_ppdu->rix;
+ rx_stats->cur_cache_idx = 0;
+ 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
@@ -283,6 +616,7 @@
ppdu_user->mcs,
ppdu_user->bw);
}
+
__tx_stats->rate = ppdu_user->tx_ratekbps;
__tx_stats->num_ppdus += num_ppdus;
__tx_stats->mpdu_attempts += mpdu_attempts;
@@ -304,13 +638,21 @@
uint8_t user_idx;
bool idx_match = false;
+ if (soc_stats_ctx->stats_ver != RDK_RATE_STATS &&
+ soc_stats_ctx->stats_ver != RDK_ALL_STATS)
+ return;
+
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;
}
@@ -318,10 +660,11 @@
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;
}
- tx_stats = &stats_ctx->tx;
+ tx_stats = &stats_ctx->rate_stats->tx;
RATE_STATS_LOCK_ACQUIRE(&tx_stats->lock);
if (qdf_likely(tx_stats->cur_rix == ppdu_user->rix)) {
@@ -329,6 +672,7 @@
__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;
}
@@ -365,17 +709,22 @@
tx_stats->cur_cache_idx = 0;
}
RATE_STATS_LOCK_RELEASE(&tx_stats->lock);
+ STATS_CTX_LOCK_RELEASE(&soc_stats_ctx->tx_ctx_lock);
}
}
static void
-wlan_peer_update_sojourn_stats(void *ctx,
+wlan_peer_update_sojourn_stats(struct wlan_soc_rate_stats_ctx *soc_stats_ctx,
struct cdp_tx_sojourn_stats *sojourn_stats)
{
struct wlan_peer_rate_stats_ctx *stats_ctx;
struct wlan_peer_tx_rate_stats *tx_stats;
uint8_t tid;
+ if (soc_stats_ctx->stats_ver != RDK_RATE_STATS &&
+ soc_stats_ctx->stats_ver != RDK_ALL_STATS)
+ return;
+
stats_ctx = (struct wlan_peer_rate_stats_ctx *)sojourn_stats->cookie;
if (qdf_unlikely(!stats_ctx)) {
@@ -383,7 +732,7 @@
return;
}
- tx_stats = &stats_ctx->tx;
+ tx_stats = &stats_ctx->rate_stats->tx;
RATE_STATS_LOCK_ACQUIRE(&tx_stats->lock);
for (tid = 0; tid < CDP_DATA_TID_MAX; tid++) {
@@ -424,12 +773,14 @@
cdp_tx_ppdu = (struct cdp_tx_completion_ppdu *)
qdf_nbuf_data(nbuf);
wlan_peer_update_tx_rate_stats(soc_stats_ctx, cdp_tx_ppdu);
+ wlan_peer_update_tx_link_stats(soc_stats_ctx, cdp_tx_ppdu);
qdf_nbuf_free(nbuf);
break;
case WDI_EVENT_RX_PPDU_DESC:
cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)
qdf_nbuf_data(nbuf);
wlan_peer_update_rx_rate_stats(soc_stats_ctx, cdp_rx_ppdu);
+ wlan_peer_update_rx_link_stats(soc_stats_ctx, cdp_rx_ppdu);
qdf_nbuf_free(nbuf);
break;
case WDI_EVENT_TX_SOJOURN_STAT:
@@ -445,33 +796,71 @@
}
}
-void wlan_peer_create_event_handler(void *pdev, enum WDI_EVENT event,
+void wlan_peer_create_event_handler(void *ctx, enum WDI_EVENT event,
void *buf, uint16_t peer_id,
uint32_t type)
{
struct cdp_peer_cookie *peer_info;
struct wlan_peer_rate_stats_ctx *stats;
+ struct wlan_soc_rate_stats_ctx *soc_stats_ctx;
uint8_t idx;
+ soc_stats_ctx = ctx;
+
peer_info = (struct cdp_peer_cookie *)buf;
stats = qdf_mem_malloc(sizeof(*stats));
if (!stats) {
qdf_err("malloc failed, returning NULL");
return;
}
- qdf_mem_zero(stats, sizeof(*stats));
- RATE_STATS_LOCK_CREATE(&stats->tx.lock);
- RATE_STATS_LOCK_CREATE(&stats->rx.lock);
+
+ if (soc_stats_ctx->stats_ver == RDK_RATE_STATS ||
+ soc_stats_ctx->stats_ver == RDK_ALL_STATS) {
+ stats->rate_stats =
+ qdf_mem_malloc(sizeof(struct wlan_peer_rate_stats));
+ if (!stats->rate_stats) {
+ qdf_err("malloc failed");
+ goto peer_create_fail1;
+ }
+ RATE_STATS_LOCK_CREATE(&stats->rate_stats->tx.lock);
+ RATE_STATS_LOCK_CREATE(&stats->rate_stats->rx.lock);
+ for (idx = 0; idx < WLANSTATS_CACHE_SIZE; idx++) {
+ stats->rate_stats->tx.stats[idx].rix =
+ INVALID_CACHE_IDX;
+ stats->rate_stats->rx.stats[idx].rix =
+ INVALID_CACHE_IDX;
+ }
+ }
+
+ if (soc_stats_ctx->stats_ver == RDK_LINK_STATS ||
+ soc_stats_ctx->stats_ver == RDK_ALL_STATS) {
+ stats->link_metrics =
+ qdf_mem_malloc(sizeof(struct wlan_peer_link_metrics));
+ if (!stats->link_metrics) {
+ qdf_err("malloc failed");
+ goto peer_create_fail2;
+ }
+ RATE_STATS_LOCK_CREATE(&stats->link_metrics->tx.lock);
+ RATE_STATS_LOCK_CREATE(&stats->link_metrics->rx.lock);
+ }
+
qdf_mem_copy(stats->mac_addr, peer_info->mac_addr, QDF_MAC_ADDR_SIZE);
stats->peer_cookie = peer_info->cookie;
stats->pdev_id = peer_info->pdev_id;
- for (idx = 0; idx < WLANSTATS_CACHE_SIZE; idx++) {
- stats->tx.stats[idx].rix = INVALID_CACHE_IDX;
- stats->rx.stats[idx].rix = INVALID_CACHE_IDX;
- }
-
peer_info->ctx = (void *)stats;
+ return;
+
+peer_create_fail2:
+ if (soc_stats_ctx->stats_ver == RDK_RATE_STATS ||
+ soc_stats_ctx->stats_ver == RDK_ALL_STATS) {
+ RATE_STATS_LOCK_DESTROY(&stats->rate_stats->tx.lock);
+ RATE_STATS_LOCK_DESTROY(&stats->rate_stats->rx.lock);
+ qdf_mem_free(stats->rate_stats);
+ stats->rate_stats = NULL;
+ }
+peer_create_fail1:
+ qdf_mem_free(stats);
}
void wlan_peer_destroy_event_handler(void *ctx, enum WDI_EVENT event,
@@ -480,16 +869,31 @@
{
struct cdp_peer_cookie *peer_info;
struct wlan_peer_rate_stats_ctx *stats;
+ struct wlan_soc_rate_stats_ctx *soc_stats_ctx;
+
+ soc_stats_ctx = ctx;
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);
- RATE_STATS_LOCK_DESTROY(&stats->tx.lock);
- RATE_STATS_LOCK_DESTROY(&stats->rx.lock);
+ if (stats->rate_stats) {
+ RATE_STATS_LOCK_DESTROY(&stats->rate_stats->tx.lock);
+ RATE_STATS_LOCK_DESTROY(&stats->rate_stats->rx.lock);
+ qdf_mem_free(stats->rate_stats);
+ }
+ if (stats->link_metrics) {
+ RATE_STATS_LOCK_DESTROY(&stats->link_metrics->tx.lock);
+ RATE_STATS_LOCK_DESTROY(&stats->link_metrics->rx.lock);
+ qdf_mem_free(stats->link_metrics);
+ }
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
diff --git a/dp/wifi3.0/dp_full_mon.c b/dp/wifi3.0/dp_full_mon.c
index f01ff8c..3a11d92 100644
--- a/dp/wifi3.0/dp_full_mon.c
+++ b/dp/wifi3.0/dp_full_mon.c
@@ -268,12 +268,14 @@
* to upper layer stack
*
* @soc: DP soc handle
+ * @pdev: pdev
* @mac_id: lmac id
*/
static inline QDF_STATUS
-dp_rx_monitor_deliver_ppdu(struct dp_soc *soc, uint32_t mac_id)
+dp_rx_monitor_deliver_ppdu(struct dp_soc *soc,
+ struct dp_pdev *pdev,
+ uint32_t mac_id)
{
- struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id);
struct dp_mon_mpdu *mpdu = NULL;
struct dp_mon_mpdu *temp_mpdu = NULL;
@@ -311,6 +313,7 @@
* status ring.
*
* @soc: DP soc handle
+ * @pdev: pdev
* @int_ctx: interrupt context
* @mac_id: mac id on which interrupt is received
* @quota: number of status ring entries to be reaped
@@ -318,12 +321,12 @@
*/
static inline uint32_t
dp_rx_mon_reap_status_ring(struct dp_soc *soc,
+ struct dp_pdev *pdev,
struct dp_intr *int_ctx,
uint32_t mac_id,
uint32_t quota,
struct hal_rx_mon_desc_info *desc_info)
{
- struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id);
uint8_t status_buf_count;
uint32_t work_done = 0;
enum dp_mon_reap_status status;
@@ -400,6 +403,7 @@
* and returns link descriptor to HW (WBM)
*
* @soc: DP soc handle
+ * @pdev: pdev
* @mac_id: lmac id
* @ring_desc: SW monitor ring desc
* @head_msdu: nbuf pointing to first msdu in a chain
@@ -410,25 +414,26 @@
* Return: number of reaped buffers
*/
static inline uint32_t
-dp_rx_mon_mpdu_reap(struct dp_soc *soc, uint32_t mac_id, void *ring_desc,
- qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu,
+dp_rx_mon_mpdu_reap(struct dp_soc *soc, struct dp_pdev *pdev, uint32_t mac_id,
+ void *ring_desc, qdf_nbuf_t *head_msdu,
+ qdf_nbuf_t *tail_msdu,
union dp_rx_desc_list_elem_t **head_desc,
union dp_rx_desc_list_elem_t **tail_desc)
{
- struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id);
struct dp_rx_desc *rx_desc = NULL;
struct hal_rx_msdu_list msdu_list;
uint32_t rx_buf_reaped = 0;
uint16_t num_msdus = 0, msdu_index, rx_hdr_tlv_len, l3_hdr_pad;
uint32_t total_frag_len = 0, frag_len = 0;
bool drop_mpdu = false;
- bool msdu_frag = false;
+ bool msdu_frag = false, is_first_msdu = true, is_frag_non_raw = false;
void *link_desc_va;
uint8_t *rx_tlv_hdr;
qdf_nbuf_t msdu = NULL, last_msdu = NULL;
uint32_t rx_link_buf_info[HAL_RX_BUFFINFO_NUM_DWORDS];
struct hal_rx_mon_desc_info *desc_info;
uint16_t prev_ppdu_id;
+ struct rx_desc_pool *rx_desc_pool = NULL;
desc_info = pdev->mon_desc;
@@ -478,24 +483,43 @@
qdf_assert_always(rx_desc);
- msdu = rx_desc->nbuf;
+ msdu = DP_RX_MON_GET_NBUF_FROM_DESC(rx_desc);
if (rx_desc->unmapped == 0) {
- qdf_nbuf_unmap_single(soc->osdev,
- msdu,
- QDF_DMA_FROM_DEVICE);
+ rx_desc_pool = dp_rx_get_mon_desc_pool(
+ soc, mac_id, pdev->pdev_id);
+ dp_rx_mon_buffer_unmap(soc, rx_desc,
+ rx_desc_pool->buf_size);
+
rx_desc->unmapped = 1;
}
if (drop_mpdu) {
- qdf_nbuf_free(msdu);
+ dp_rx_mon_buffer_free(rx_desc);
msdu = NULL;
desc_info->msdu_count--;
goto next_msdu;
}
- rx_tlv_hdr = qdf_nbuf_data(msdu);
+ rx_tlv_hdr = dp_rx_mon_get_buffer_data(rx_desc);
+ if (is_first_msdu) {
+ if (dp_rx_mon_alloc_parent_buffer(head_msdu)
+ != QDF_STATUS_SUCCESS) {
+ DP_STATS_INC(pdev,
+ replenish.nbuf_alloc_fail,
+ 1);
+ qdf_frag_free(rx_tlv_hdr);
+ QDF_TRACE(QDF_MODULE_ID_DP,
+ QDF_TRACE_LEVEL_DEBUG,
+ "[%s] failed to allocate parent buffer to hold all frag",
+ __func__);
+ drop_mpdu = true;
+ desc_info->msdu_count--;
+ goto next_msdu;
+ }
+ is_first_msdu = false;
+ }
if (hal_rx_desc_is_first_msdu(soc->hal_soc,
rx_tlv_hdr))
hal_rx_mon_hw_desc_get_mpdu_status(soc->hal_soc,
@@ -508,23 +532,16 @@
* b. calculate the number of fragmented buffers for
* a msdu and decrement one msdu_count
*/
- if (msdu_list.msdu_info[msdu_index].msdu_flags
- & HAL_MSDU_F_MSDU_CONTINUATION) {
- if (!msdu_frag) {
- total_frag_len = msdu_list.msdu_info[msdu_index].msdu_len;
- msdu_frag = true;
- }
- dp_mon_adjust_frag_len(&total_frag_len,
- &frag_len);
- } else {
- if (msdu_frag)
- dp_mon_adjust_frag_len(&total_frag_len,
- &frag_len);
- else
- frag_len = msdu_list.msdu_info[msdu_index].msdu_len;
- msdu_frag = false;
+ dp_rx_mon_parse_desc_buffer(soc,
+ &(msdu_list.msdu_info[msdu_index]),
+ &msdu_frag,
+ &total_frag_len,
+ &frag_len,
+ &l3_hdr_pad,
+ rx_tlv_hdr,
+ &is_frag_non_raw, rx_tlv_hdr);
+ if (!msdu_frag)
desc_info->msdu_count--;
- }
rx_hdr_tlv_len = SIZE_OF_MONITOR_TLV;
@@ -535,9 +552,6 @@
* header begins.
*/
- l3_hdr_pad = hal_rx_msdu_end_l3_hdr_padding_get(
- soc->hal_soc,
- rx_tlv_hdr);
/*******************************************************
* RX_PACKET *
@@ -546,17 +560,14 @@
* ----------------------------------------------------*
******************************************************/
- qdf_nbuf_set_pktlen(msdu,
- rx_hdr_tlv_len +
- l3_hdr_pad +
- frag_len);
+ dp_rx_mon_buffer_set_pktlen(msdu,
+ rx_hdr_tlv_len +
+ l3_hdr_pad +
+ frag_len);
- if (head_msdu && !*head_msdu)
- *head_msdu = msdu;
- else if (last_msdu)
- qdf_nbuf_set_next(last_msdu, msdu);
-
- last_msdu = msdu;
+ dp_rx_mon_add_msdu_to_list(head_msdu, msdu, &last_msdu,
+ rx_tlv_hdr, frag_len,
+ l3_hdr_pad);
next_msdu:
rx_buf_reaped++;
@@ -592,10 +603,8 @@
}
pdev->rx_mon_stats.dest_mpdu_done++;
- if (last_msdu)
- qdf_nbuf_set_next(last_msdu, NULL);
-
- *tail_msdu = msdu;
+ dp_rx_mon_init_tail_msdu(msdu, last_msdu, tail_msdu);
+ dp_rx_mon_remove_raw_frame_fcs_len(head_msdu);
return rx_buf_reaped;
}
@@ -701,7 +710,7 @@
work_done += dp_rx_mon_status_process(soc, int_ctx, mac_id,
desc_info->status_buf_count);
- dp_rx_monitor_deliver_ppdu(soc, mac_id);
+ dp_rx_monitor_deliver_ppdu(soc, pdev, mac_id);
}
return work_done;
@@ -793,7 +802,7 @@
hal_srng_dst_peek(hal_soc, mon_dest_srng))) {
head_msdu = NULL;
tail_msdu = NULL;
- rx_bufs_reaped = dp_rx_mon_mpdu_reap(soc, mac_id,
+ rx_bufs_reaped = dp_rx_mon_mpdu_reap(soc, pdev, mac_id,
ring_desc, &head_msdu,
&tail_msdu, &head_desc,
&tail_desc);
@@ -900,13 +909,13 @@
*/
rx_mon_stats->dest_ppdu_done++;
- work_done += dp_rx_mon_reap_status_ring(soc, int_ctx, mac_id,
- quota, desc_info);
+ work_done += dp_rx_mon_reap_status_ring(soc, pdev, int_ctx,
+ mac_id, quota, desc_info);
/* Deliver all MPDUs for a PPDU */
if (desc_info->drop_ppdu)
dp_rx_mon_drop_ppdu(pdev, mac_id);
else if (!pdev->hold_mon_dest_ring)
- dp_rx_monitor_deliver_ppdu(soc, mac_id);
+ dp_rx_monitor_deliver_ppdu(soc, pdev, mac_id);
next_entry:
hal_srng_dst_get_next(hal_soc, mon_dest_srng);
diff --git a/dp/wifi3.0/dp_rx_tag.c b/dp/wifi3.0/dp_rx_tag.c
index 3c30400..608eb9f 100644
--- a/dp/wifi3.0/dp_rx_tag.c
+++ b/dp/wifi3.0/dp_rx_tag.c
@@ -96,6 +96,39 @@
* Return: void
*/
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
+
+#ifdef DP_RX_MON_MEM_FRAG
+/**
+ * dp_rx_update_proto_tag() - Update protocol tag to nbuf cb or to headroom
+ *
+ * @nbuf: QDF pkt buffer on which the protocol tag should be set
+ * @protocol_tag: Protocol tag
+ */
+static inline
+void dp_rx_update_proto_tag(qdf_nbuf_t nbuf, uint16_t protocol_tag)
+{
+ uint8_t idx;
+ uint8_t *nbuf_head = NULL;
+
+ if (qdf_nbuf_get_nr_frags(nbuf)) {
+ /* Get frag index, which was saved while restitch */
+ idx = QDF_NBUF_CB_RX_CTX_ID(nbuf);
+ nbuf_head = qdf_nbuf_head(nbuf);
+ nbuf_head += (idx * DP_RX_MON_PF_TAG_SIZE);
+
+ *((uint16_t *)nbuf_head) = protocol_tag;
+ } else {
+ qdf_nbuf_set_rx_protocol_tag(nbuf, protocol_tag);
+ }
+}
+#else
+static inline
+void dp_rx_update_proto_tag(qdf_nbuf_t nbuf, uint16_t protocol_tag)
+{
+ qdf_nbuf_set_rx_protocol_tag(nbuf, protocol_tag);
+}
+#endif
+
void
dp_rx_update_protocol_tag(struct dp_soc *soc, struct dp_vdev *vdev,
qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
@@ -156,7 +189,8 @@
* received protocol type.
*/
protocol_tag = pdev->rx_proto_tag_map[cce_metadata].tag;
- qdf_nbuf_set_rx_protocol_tag(nbuf, protocol_tag);
+
+ dp_rx_update_proto_tag(nbuf, protocol_tag);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW,
"Seq:%u dcap:%u CCE Match:%u ProtoID:%u Tag:%u stats:%u",
hal_rx_get_rx_sequence(soc->hal_soc, rx_tlv_hdr),
@@ -189,6 +223,41 @@
* Return: void
*/
#ifdef WLAN_SUPPORT_RX_FLOW_TAG
+
+#ifdef DP_RX_MON_MEM_FRAG
+/**
+ * dp_rx_update_flow_tags() - Update protocol tag to nbuf cb or to headroom
+ *
+ * @nbuf: QDF pkt buffer on which the protocol tag should be set
+ * @flow_tag: Flow tag
+ */
+static inline
+void dp_rx_update_flow_tags(qdf_nbuf_t nbuf, uint32_t flow_tag)
+{
+ uint8_t idx;
+ uint8_t *nbuf_head = NULL;
+ uint16_t updated_flow_tag = (uint16_t)(flow_tag & 0xFFFF);
+
+ if (qdf_nbuf_get_nr_frags(nbuf)) {
+ /* Get frag index, which was saved while restitch */
+ idx = QDF_NBUF_CB_RX_CTX_ID(nbuf);
+ nbuf_head = qdf_nbuf_head(nbuf);
+ nbuf_head += ((idx * DP_RX_MON_PF_TAG_SIZE) +
+ sizeof(uint16_t));
+
+ *((uint16_t *)nbuf_head) = updated_flow_tag;
+ } else {
+ qdf_nbuf_set_rx_flow_tag(nbuf, flow_tag);
+ }
+}
+#else
+static inline
+void dp_rx_update_flow_tags(qdf_nbuf_t nbuf, uint16_t flow_tag)
+{
+ qdf_nbuf_set_rx_flow_tag(nbuf, flow_tag);
+}
+#endif
+
void
dp_rx_update_flow_tag(struct dp_soc *soc, struct dp_vdev *vdev,
qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, bool update_stats)
@@ -240,7 +309,7 @@
fse_metadata = hal_rx_msdu_fse_metadata_get(soc->hal_soc, rx_tlv_hdr) & 0xFFFF;
/* update the skb->cb with the user-specified tag/metadata */
- qdf_nbuf_set_rx_flow_tag(nbuf, fse_metadata);
+ dp_rx_update_flow_tags(nbuf, fse_metadata);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW,
"Seq:%u dcap:%u invalid:%u timeout:%u flow:%u tag:%u stat:%u",
diff --git a/dp/wifi3.0/dp_rx_tag.h b/dp/wifi3.0/dp_rx_tag.h
index a3b79e8..21013ce 100644
--- a/dp/wifi3.0/dp_rx_tag.h
+++ b/dp/wifi3.0/dp_rx_tag.h
@@ -22,6 +22,10 @@
#include "dp_internal.h"
#include "dp_types.h"
+#ifdef DP_RX_MON_MEM_FRAG
+#define DP_RX_MON_PF_TAG_SIZE (4)
+#endif
+
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
/**
* dp_update_pdev_rx_protocol_tag - Add/remove a protocol tag that should be
diff --git a/dp/wifi3.0/dp_tx_capture.c b/dp/wifi3.0/dp_tx_capture.c
index 9c4d485..9946795 100644
--- a/dp/wifi3.0/dp_tx_capture.c
+++ b/dp/wifi3.0/dp_tx_capture.c
@@ -6274,11 +6274,11 @@
/* initialize ppdu_desc_log to 1 */
ptr_log_info->ppdu_desc_log = 1;
} else {
- /* if ppdu_desc log already 1 return success */
- if (ptr_log_info->ppdu_desc_log)
+ /* if ppdu_desc log already 0 return success */
+ if (!ptr_log_info->ppdu_desc_log)
return QDF_STATUS_SUCCESS;
- /* initialize ppdu_desc_log to 1 */
+ /* initialize ppdu_desc_log to 0 */
ptr_log_info->ppdu_desc_log = 0;
}
return QDF_STATUS_SUCCESS;
diff --git a/tools/linux/cfg80211_ven_cmd.h b/tools/linux/cfg80211_ven_cmd.h
index 3ae5d9c..3aa838d 100644
--- a/tools/linux/cfg80211_ven_cmd.h
+++ b/tools/linux/cfg80211_ven_cmd.h
@@ -761,6 +761,7 @@
IEEE80211_PARAM_OCE_TX_POWER = 696, /* Enables tx power to be advertised as OCE attribute in Beacon and Probe response frame */
IEEE80211_PARAM_OCE_IP_SUBNET_ID = 697, /* IP subnet identifier value to be advertised as OCE attribute in Beacon and Probe response frame */
IEEE80211_PARAM_OCE_ADD_ESS_RPT = 698, /* Add ESS Report */
+ IEEE80211_PARAM_ENABLE_MSCS = 699, /* Enable MSCS */
IEEE80211_PARAM_RSNX_OVERRIDE = 700,
#if QCA_AIRTIME_FAIRNESS
IEEE80211_PARAM_ATF_ENABLE_STATS = 701,
@@ -1203,6 +1204,28 @@
OL_ATH_PARAM_RPT_MAX_PHY = 446,
/* Enable additional operating triplets in the Country IE */
OL_ATH_PARAM_ENABLE_ADDITIONAL_TRIPLETS = 447,
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+ /* Set the primary frequency for the AP to go back to, after NOL */
+ OL_ATH_DFS_CHAN_POSTNOL_FREQ = 448,
+ /* Set the mode for the AP to go back to, after NOL */
+ OL_ATH_DFS_CHAN_POSTNOL_MODE = 449,
+ /* Set the secondary center frequency for the post NOL channel. */
+ OL_ATH_DFS_CHAN_POSTNOL_CFREQ2 = 450,
+#endif
+ /* DCS Wideband (5-7GHz) policy */
+ OL_ATH_PARAM_DCS_WIDEBAND_POLICY = 451,
+#ifdef QCA_CBT_INSTRUMENTATION
+ /* Support get_call_map() for CBT */
+ OL_ATH_PARAM_FUNC_CALL_MAP = 452,
+#endif
+ /* Configure punctured band setting */
+ OL_ATH_PARAM_PUNCTURED_BAND = 453,
+ /* Control frame configuration for MBSSID */
+ OL_ATH_PARAM_HE_MBSSID_CTRL_FRAME_CONFIG = 454,
+ /* Max users per-PPDU for OFDMA, 16 LSBs for DL and 16 MSBs for UL */
+ OL_ATH_PARAM_OFDMA_MAX_USERS = 455,
+ /* Max users per-PPDU for MU-MIMO, 16 LSBs for DL and 16 MSBs for UL */
+ OL_ATH_PARAM_MUMIMO_MAX_USERS = 456,
};
@@ -2167,6 +2190,8 @@
{"rsim_de_frmcnt", IEEE80211_PARAM_RAWSIM_DEBUG_NUM_DECAP_FRAMES, SET_PARAM, 1},
{"g_rsim_de_frmcnt", IEEE80211_PARAM_RAWSIM_DEBUG_NUM_DECAP_FRAMES, GET_PARAM, 0},
#endif
+ {"mscs", IEEE80211_PARAM_ENABLE_MSCS, SET_PARAM, 1},
+ {"g_mscs", IEEE80211_PARAM_ENABLE_MSCS, GET_PARAM, 0},
{"setiebuf", 35828, SET_PARAM, 1},
{"getiebuf", 35827, GET_PARAM, 0},
{"dbgreq", 35832, SET_PARAM, 1},
@@ -3103,6 +3128,40 @@
OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_ENABLE_ADDITIONAL_TRIPLETS, SET_PARAM, 1},
{"g_enable_additional_triplets",
OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_ENABLE_ADDITIONAL_TRIPLETS, GET_PARAM, 0},
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+ {"setpostNOLfreq",
+ OL_ATH_PARAM_SHIFT | OL_ATH_DFS_CHAN_POSTNOL_FREQ, SET_PARAM, 1},
+ {"getpostNOLfreq",
+ OL_ATH_PARAM_SHIFT | OL_ATH_DFS_CHAN_POSTNOL_FREQ, GET_PARAM, 0},
+ {"setpostNOLmode",
+ OL_ATH_PARAM_SHIFT | OL_ATH_DFS_CHAN_POSTNOL_MODE, SET_PARAM, 1},
+ {"getpostNOLmode",
+ OL_ATH_PARAM_SHIFT | OL_ATH_DFS_CHAN_POSTNOL_MODE, SET_PARAM, 0},
+ {"setpostNOLcfreq2",
+ OL_ATH_PARAM_SHIFT | OL_ATH_DFS_CHAN_POSTNOL_CFREQ2, SET_PARAM, 1},
+ {"getpostNOLcfreq2",
+ OL_ATH_PARAM_SHIFT | OL_ATH_DFS_CHAN_POSTNOL_CFREQ2, GET_PARAM, 0},
+#endif
+ {"dcs_wideband_policy",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_DCS_WIDEBAND_POLICY, SET_PARAM, 1},
+ {"get_dcs_wideband_policy",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_DCS_WIDEBAND_POLICY, GET_PARAM, 0},
+#ifdef QCA_CBT_INSTRUMENTATION
+ {"get_call_map",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_FUNC_CALL_MAP, SET_PARAM, 1},
+#endif
+ {"puncture_band",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_PUNCTURED_BAND, SET_PARAM, 1},
+ {"get_puncture_band",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_PUNCTURED_BAND, GET_PARAM, 0},
+ {"he_mbssid_ctrl_frame_config",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_HE_MBSSID_CTRL_FRAME_CONFIG, SET_PARAM, 1},
+ {"g_he_mbssid_ctrl_frame_config",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_HE_MBSSID_CTRL_FRAME_CONFIG, GET_PARAM, 0},
+ {"get_ofdma_usr",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_OFDMA_MAX_USERS, GET_PARAM, 0},
+ {"get_mumimo_usr",
+ OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_MUMIMO_MAX_USERS, GET_PARAM, 0},
};
#endif
#endif
diff --git a/tools/linux/peerstats.c b/tools/linux/peerstats.c
index 0cd1a65..952784d 100644
--- a/tools/linux/peerstats.c
+++ b/tools/linux/peerstats.c
@@ -340,6 +340,100 @@
return;
}
+static void dp_peer_tx_link_stats_print(uint8_t *peer_mac,
+ uint64_t peer_cookie,
+ void *buffer,
+ uint32_t buffer_len)
+{
+ struct wlan_tx_link_stats *tx_stats;
+ uint8_t is_lithium;
+
+ is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
+ >> WLANSTATS_PEER_COOKIE_LSB;
+
+ if (!is_lithium) {
+ PRINT("Not supported in non-lithium platforms\n");
+ return;
+ }
+
+ if (buffer_len < sizeof(struct wlan_tx_link_stats)) {
+ PRINT("invalid buffer len, return");
+ return;
+ }
+
+ tx_stats = (struct wlan_tx_link_stats *)buffer;
+
+ PRINT("\n\n");
+ PRINT("========= PEER TX LINK QUALITY METRICS =========\n");
+ PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx",
+ peer_mac[0],
+ peer_mac[1],
+ peer_mac[2],
+ peer_mac[3],
+ peer_mac[4],
+ peer_mac[5]);
+ PRINT("num_ppdus: %u", tx_stats->num_ppdus);
+ PRINT("bytes: %"PRIu64, tx_stats->bytes);
+ PRINT("phy_rate_actual_su: %u kbps", tx_stats->phy_rate_actual_su);
+ PRINT("phy_rate_actual_mu: %u kbps", tx_stats->phy_rate_actual_mu);
+ PRINT("ofdma_usage: %u", tx_stats->ofdma_usage);
+ PRINT("mu_mimo_usage: %u", tx_stats->mu_mimo_usage);
+ PRINT("bw_usage_avg: %u MHz", tx_stats->bw.usage_avg);
+ PRINT("bw_usage_packets: 20MHz: %u 40MHz: %u 80MHz: %u 160MHz: %u",
+ tx_stats->bw.usage_counter[0], tx_stats->bw.usage_counter[1],
+ tx_stats->bw.usage_counter[2], tx_stats->bw.usage_counter[3]);
+ PRINT("bw_usage_max:: %u%%", tx_stats->bw.usage_max);
+ PRINT("ack_rssi: %lu", tx_stats->ack_rssi);
+ PRINT("pkt_error_rate: %u%%", tx_stats->pkt_error_rate);
+}
+
+static void dp_peer_rx_link_stats_print(uint8_t *peer_mac,
+ uint64_t peer_cookie,
+ void *buffer,
+ uint32_t buffer_len)
+{
+ struct wlan_rx_link_stats *rx_stats;
+ uint8_t is_lithium;
+
+ is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
+ >> WLANSTATS_PEER_COOKIE_LSB;
+
+ if (!is_lithium) {
+ PRINT("Not supported in non-lithium platforms\n");
+ return;
+ }
+
+ if (buffer_len < sizeof(struct wlan_rx_link_stats)) {
+ PRINT("invalid buffer len, return");
+ return;
+ }
+
+ rx_stats = (struct wlan_rx_link_stats *)buffer;
+
+ PRINT("\n\n");
+ PRINT("========= PEER RX LINK QUALITY METRICS =========\n");
+ PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx",
+ peer_mac[0],
+ peer_mac[1],
+ peer_mac[2],
+ peer_mac[3],
+ peer_mac[4],
+ peer_mac[5]);
+ PRINT("num_ppdus: %u", rx_stats->num_ppdus);
+ PRINT("bytes: %"PRIu64, rx_stats->bytes);
+ PRINT("phy_rate_actual_su: %u kbps", rx_stats->phy_rate_actual_su);
+ PRINT("phy_rate_actual_mu: %u kbps", rx_stats->phy_rate_actual_mu);
+ PRINT("ofdma_usage: %u", rx_stats->ofdma_usage);
+ PRINT("mu_mimo_usage: %u", rx_stats->mu_mimo_usage);
+ PRINT("bw_usage_avg: %u MHz", rx_stats->bw.usage_avg);
+ PRINT("bw_usage_packets: 20MHz: %u 40MHz: %u 80MHz: %u 160MHz: %u",
+ rx_stats->bw.usage_counter[0], rx_stats->bw.usage_counter[1],
+ rx_stats->bw.usage_counter[2], rx_stats->bw.usage_counter[3]);
+ PRINT("bw_usage_max: %u%%", rx_stats->bw.usage_max);
+ PRINT("su_rssi: %lu", rx_stats->su_rssi);
+ PRINT("pkt_error_rate: %u%%", rx_stats->pkt_error_rate);
+}
+
static void dp_peer_stats_handler(uint32_t cache_type,
uint8_t *peer_mac,
uint64_t peer_cookie,
@@ -355,6 +449,14 @@
dp_peer_tx_rate_stats_print(peer_mac, peer_cookie,
buffer, buffer_len);
break;
+ case DP_PEER_TX_LINK_STATS:
+ dp_peer_tx_link_stats_print(peer_mac, peer_cookie,
+ buffer, buffer_len);
+ break;
+ case DP_PEER_RX_LINK_STATS:
+ dp_peer_rx_link_stats_print(peer_mac, peer_cookie,
+ buffer, buffer_len);
+ break;
}
}
diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_utils_api.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_utils_api.h
index dc1b9f1..0ab1f64 100644
--- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_utils_api.h
+++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_ic_utils_api.h
@@ -40,7 +40,7 @@
peer_cp_stats_##field##_dec(struct wlan_objmgr_peer *_peer, \
uint64_t _val) \
{ \
- ucfg_peer_cp_stats_##field##_inc(_peer, _val); \
+ ucfg_peer_cp_stats_##field##_dec(_peer, _val); \
} \
static inline void \
peer_cp_stats_##field##_update(struct wlan_objmgr_peer *_peer, \
diff --git a/umac/dfs/core/src/misc/dfs_zero_cac.c b/umac/dfs/core/src/misc/dfs_zero_cac.c
index fe84861..2134008 100644
--- a/umac/dfs/core/src/misc/dfs_zero_cac.c
+++ b/umac/dfs/core/src/misc/dfs_zero_cac.c
@@ -273,10 +273,12 @@
dfs->dfs_precac_secondary_freq_mhz = 0;
}
+#if defined(ATH_SUPPORT_ZERO_CAC_DFS) && !defined(QCA_MCL_DFS_SUPPORT)
void dfs_zero_cac_timer_detach(struct dfs_soc_priv_obj *dfs_soc_obj)
{
qdf_timer_free(&dfs_soc_obj->dfs_precac_timer);
}
+#endif
int dfs_override_precac_timeout(struct wlan_dfs *dfs, int precac_timeout)
{
@@ -514,6 +516,13 @@
bool ret_val = 0;
uint16_t cfreq;
+ if (!WLAN_IS_CHAN_5GHZ(chan)) {
+ dfs_debug(dfs, WLAN_DEBUG_DFS,
+ "Channel %d not a 5GHz channel",
+ chan->dfs_ch_ieee);
+ return 0;
+ }
+
if (WLAN_IS_CHAN_MODE_160(chan))
cfreq = chan->dfs_ch_mhz_freq_seg2;
else if (WLAN_IS_CHAN_MODE_165(dfs, chan))
@@ -1474,6 +1483,7 @@
}
}
+#if defined(ATH_SUPPORT_ZERO_CAC_DFS) && !defined(QCA_MCL_DFS_SUPPORT)
void dfs_zero_cac_timer_init(struct dfs_soc_priv_obj *dfs_soc_obj)
{
dfs_soc_obj->precac_state_started = false;
@@ -1482,6 +1492,7 @@
(void *)dfs_soc_obj,
QDF_TIMER_TYPE_WAKE_APPS);
}
+#endif
void dfs_zero_cac_attach(struct wlan_dfs *dfs)
{
@@ -1883,6 +1894,8 @@
precac_entry->center_ch_ieee =
utils_dfs_freq_to_chan(precac_center_freq);
precac_entry->bw = dfs_max_bw_info[index].dfs_max_bw;
+ /* non_dfs_subch_count will be updated once the channels are marked. */
+ precac_entry->non_dfs_subch_count = 0;
precac_entry->dfs = dfs;
status =
dfs_create_precac_tree_for_freq(dfs,
@@ -1910,6 +1923,8 @@
precac_entry->center_ch_ieee =
utils_dfs_freq_to_chan(precac_entry->center_ch_freq);
precac_entry->bw = DFS_CHWIDTH_160_VAL;
+ /* non_dfs_subch_count will be updated once the channels are marked. */
+ precac_entry->non_dfs_subch_count = 0;
precac_entry->dfs = dfs;
dfs_insert_node_into_bstree_for_freq(&precac_entry->tree_root,
RESTRICTED_80P80_CHAN_CENTER_FREQ,
@@ -1934,6 +1949,35 @@
return status;
}
+/**
+ * dfs_update_non_dfs_subchannel_count() - API to update the preCAC entry
+ * with the given non DFS subchannel count.
+ * @dfs: Pointer to DFS object.
+ * @frequency: Frequency whose corresponding preCAC entry needs to be updated.
+ * @count: Non DFS subchannel count for the preCAC entry.
+ */
+static void
+dfs_update_non_dfs_subchannel_count(struct wlan_dfs *dfs,
+ qdf_freq_t frequency,
+ uint8_t count)
+{
+ struct dfs_precac_entry *precac_entry = NULL, *tmp_precac_entry = NULL;
+
+ PRECAC_LIST_LOCK(dfs);
+ TAILQ_FOREACH_SAFE(precac_entry,
+ &dfs->dfs_precac_list,
+ pe_list,
+ tmp_precac_entry) {
+ if (IS_WITHIN_RANGE_STRICT(frequency,
+ precac_entry->center_ch_freq,
+ (precac_entry->bw/2))) {
+ precac_entry->non_dfs_subch_count = count;
+ break;
+ }
+ }
+ PRECAC_LIST_UNLOCK(dfs);
+}
+
static void
dfs_mark_non_dfs_as_precac_done(struct wlan_dfs *dfs,
uint16_t dfs_pri_ch_freq,
@@ -1960,6 +2004,9 @@
ichan->dfs_ch_mhz_freq_seg1,
0,
CH_WIDTH_80MHZ);
+ dfs_update_non_dfs_subchannel_count(dfs,
+ ichan->dfs_ch_mhz_freq_seg1,
+ N_SUBCHANS_FOR_80BW);
PRECAC_LIST_LOCK(dfs);
} else if (!WLAN_IS_CHAN_DFS_CFREQ2(ichan)) {
PRECAC_LIST_UNLOCK(dfs);
@@ -1967,6 +2014,9 @@
ichan->dfs_ch_mhz_freq_seg2,
0,
CH_WIDTH_80MHZ);
+ dfs_update_non_dfs_subchannel_count(dfs,
+ ichan->dfs_ch_mhz_freq_seg2,
+ N_SUBCHANS_FOR_80BW);
PRECAC_LIST_LOCK(dfs);
}
}
@@ -2209,14 +2259,12 @@
{
struct dfs_soc_priv_obj *dfs_soc_obj;
- dfs_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
- WLAN_UMAC_COMP_DFS);
+ dfs_soc_obj = dfs->dfs_soc_obj;
dfs->dfs_psoc_idx = dfs_soc_obj->num_dfs_privs;
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
"dfs->dfs_psoc_idx: %d ", dfs->dfs_psoc_idx);
dfs_soc_obj->dfs_priv[dfs_soc_obj->num_dfs_privs].dfs = dfs;
dfs_soc_obj->num_dfs_privs++;
- dfs->dfs_soc_obj = dfs_soc_obj;
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_soc_obj->num_dfs_privs: %d ",
dfs_soc_obj->num_dfs_privs);
@@ -2910,6 +2958,54 @@
}
}
+/**
+ * dfs_is_precac_completed_count_non_zero() - API to find if the preCAC
+ * completed channels count is zero/non_zero.
+ * @dfs: Pointer to DFS object.
+ *
+ * Return true, if there exists atleast one node/subchannel in the preCAC list
+ * that is CAC done, else return false.
+ */
+static bool
+dfs_is_precac_completed_count_non_zero(struct wlan_dfs *dfs)
+{
+ struct dfs_precac_entry *precac_entry = NULL;
+
+ PRECAC_LIST_LOCK(dfs);
+ if (!TAILQ_EMPTY(&dfs->dfs_precac_list)) {
+ TAILQ_FOREACH(precac_entry,
+ &dfs->dfs_precac_list,
+ pe_list) {
+ /* Find if the tree root has any preCAC channels
+ * that is CAC done.
+ */
+ if (!precac_entry->tree_root->n_caced_subchs)
+ continue;
+ if (abs(precac_entry->tree_root->n_caced_subchs -
+ precac_entry->non_dfs_subch_count)) {
+ PRECAC_LIST_UNLOCK(dfs);
+ return true;
+ }
+ }
+ }
+ PRECAC_LIST_UNLOCK(dfs);
+
+ return false;
+}
+
+enum precac_status_for_chan
+dfs_precac_status_for_channel(struct wlan_dfs *dfs,
+ struct dfs_channel *deschan)
+{
+ if (!dfs_is_precac_completed_count_non_zero(dfs))
+ return DFS_NO_PRECAC_COMPLETED_CHANS;
+
+ if (dfs_is_precac_done(dfs, deschan))
+ return DFS_PRECAC_COMPLETED_CHAN;
+
+ return DFS_PRECAC_REQUIRED_CHAN;
+}
+
void dfs_print_precaclists(struct wlan_dfs *dfs)
{
struct dfs_precac_entry *tmp_precac_entry;
@@ -3542,6 +3638,12 @@
if (WLAN_IS_CHAN_MODE_165(dfs, dfs->dfs_curchan))
flags |= DFS_RANDOM_CH_FLAG_RESTRICTED_80P80_ENABLED;
+ if (!WLAN_IS_CHAN_5GHZ(dfs->dfs_curchan)) {
+ dfs_debug(dfs, WLAN_DEBUG_DFS_AGILE,
+ "Current operating channel not a 5G channel");
+ goto exit;
+ }
+
dfs_fill_des_rcac_chan_params(dfs,
&nxt_chan_params,
curchan_chwidth);
@@ -4977,3 +5079,96 @@
}
#endif
#endif
+
+#if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) || \
+ defined(QCA_SUPPORT_ADFS_RCAC)
+QDF_STATUS
+dfs_process_radar_ind_on_agile_chan(struct wlan_dfs *dfs,
+ struct radar_found_info *radar_found)
+{
+ uint32_t freq_center;
+ uint32_t radarfound_freq;
+ QDF_STATUS status;
+ uint8_t num_channels;
+ uint16_t freq_list[NUM_CHANNELS_160MHZ];
+ uint16_t nol_freq_list[NUM_CHANNELS_160MHZ];
+ bool is_radar_source_agile =
+ (radar_found->detector_id == dfs_get_agile_detector_id(dfs));
+
+ if ((!dfs_is_agile_precac_enabled(dfs) &&
+ !dfs_is_agile_rcac_enabled(dfs)) ||
+ !dfs->dfs_agile_precac_freq_mhz) {
+ dfs_err(dfs, WLAN_DEBUG_DFS,
+ "radar on Agile detector when ADFS is not running");
+ status = QDF_STATUS_E_FAILURE;
+ goto exit;
+ }
+
+ dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center);
+ radarfound_freq = freq_center + radar_found->freq_offset;
+ if (is_radar_source_agile)
+ dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+ "Radar found on Agile detector freq=%d radar freq=%d",
+ freq_center, radarfound_freq);
+ else if (radar_found->segment_id == SEG_ID_SECONDARY)
+ dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+ "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.",
+ radarfound_freq, freq_center);
+ utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq,
+ WLAN_EV_RADAR_DETECTED);
+ if (!dfs->dfs_use_nol) {
+ dfs_reset_bangradar(dfs);
+ dfs_send_csa_to_current_chan(dfs);
+ status = QDF_STATUS_SUCCESS;
+ goto exit;
+ }
+
+ num_channels = dfs_find_radar_affected_channels(dfs,
+ radar_found,
+ freq_list,
+ freq_center);
+
+ dfs_reset_bangradar(dfs);
+
+ status = dfs_radar_add_channel_list_to_nol_for_freq(dfs,
+ freq_list,
+ nol_freq_list,
+ &num_channels);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ dfs_err(dfs, WLAN_DEBUG_DFS,
+ "radar event received on invalid channel");
+ goto exit;
+ }
+ /*
+ * If precac is running and the radar found in secondary
+ * VHT80 mark the channel as radar and add to NOL list.
+ * Otherwise random channel selection can choose this
+ * channel.
+ */
+ dfs_debug(dfs, WLAN_DEBUG_DFS,
+ "found_on_second=%d is_pre=%d",
+ dfs->is_radar_found_on_secondary_seg,
+ dfs_is_precac_timer_running(dfs));
+ /*
+ * Even if radar found on primary, we need to mark the channel as NOL
+ * in preCAC list. The preCAC list also maintains the current CAC
+ * channels as part of pre-cleared DFS. Hence call the API
+ * to mark channels as NOL irrespective of preCAC being enabled or not.
+ */
+
+ dfs_debug(dfs, WLAN_DEBUG_DFS,
+ "%s: %d Radar found on dfs detector:%d",
+ __func__, __LINE__, radar_found->detector_id);
+ dfs_mark_precac_nol_for_freq(dfs,
+ dfs->is_radar_found_on_secondary_seg,
+ radar_found->detector_id,
+ nol_freq_list,
+ num_channels);
+ if (is_radar_source_agile)
+ utils_dfs_agile_sm_deliver_evt(dfs->dfs_pdev_obj,
+ DFS_AGILE_SM_EV_ADFS_RADAR);
+
+exit:
+ return status;
+}
+#endif
diff --git a/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm_actions.c b/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm_actions.c
index 459979c..5163ce5 100644
--- a/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm_actions.c
+++ b/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm_actions.c
@@ -220,6 +220,8 @@
!wlan_util_map_is_any_index_set(
pdev_mlme->restart_send_vdev_bmap,
sizeof(pdev_mlme->restart_send_vdev_bmap))) {
+ mlme_err("Clear MVR bit for Pdev %d",
+ wlan_objmgr_pdev_get_pdev_id(pdev));
wlan_pdev_mlme_op_clear
(pdev,
WLAN_PDEV_OP_RESTART_INPROGRESS);
@@ -359,6 +361,8 @@
if (!wlan_util_map_is_any_index_set(
pdev_mlme->restart_pend_vdev_bmap,
sizeof(pdev_mlme->restart_pend_vdev_bmap))) {
+ mlme_err("Sending MVR for Pdev %d",
+ wlan_objmgr_pdev_get_pdev_id(pdev));
wlan_pdev_mlme_op_clear(pdev, WLAN_PDEV_OP_MBSSID_RESTART);
wlan_pdev_mlme_op_clear(pdev, WLAN_PDEV_OP_RESTART_INPROGRESS);