diff --git a/dp/inc/cdp_txrx_host_stats.h b/dp/inc/cdp_txrx_host_stats.h index 8f98804a13..4cc493e3ae 100644 --- a/dp/inc/cdp_txrx_host_stats.h +++ b/dp/inc/cdp_txrx_host_stats.h @@ -1061,4 +1061,56 @@ static inline QDF_STATUS cdp_get_peer_extd_rate_link_stats( return soc->ops->host_stats_ops->txrx_get_peer_extd_rate_link_stats( soc, mac_addr); } + +/* + * cdp_get_pdev_obss_pd_stats(): function to get pdev obss stats + * @soc: soc handle + * @pdev_id: pdev id + * @stats: pointer to pdev obss stats + * + * return: status + */ +static inline QDF_STATUS cdp_get_pdev_obss_pd_stats( + ol_txrx_soc_handle soc, + uint8_t pdev_id, + struct cdp_pdev_obss_pd_stats_tlv *stats) +{ + if (!soc || !soc->ops) { + dp_cdp_debug("Invalid Instance"); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->host_stats_ops || + !soc->ops->host_stats_ops->get_pdev_obss_stats) + return QDF_STATUS_E_FAILURE; + + return soc->ops->host_stats_ops->get_pdev_obss_stats( + soc, pdev_id, stats); +} + +/** + * cdp_clear_pdev_obss_pd_stats(): function to clear pdev obss stats + * @soc: soc handle + * @pdev_id: pdev id + * + * return: status + */ +static inline QDF_STATUS cdp_clear_pdev_obss_pd_stats( + ol_txrx_soc_handle soc, + uint8_t pdev_id) +{ + if (!soc || !soc->ops) { + dp_cdp_debug("Invalid Instance"); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->host_stats_ops || + !soc->ops->host_stats_ops->clear_pdev_obss_pd_stats) + return QDF_STATUS_E_FAILURE; + + return soc->ops->host_stats_ops->clear_pdev_obss_pd_stats( + soc, pdev_id); +} #endif /* _CDP_TXRX_HOST_STATS_H_ */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 4cd6104bf7..19e4dbf03c 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -1213,6 +1213,11 @@ struct cdp_host_stats_ops { QDF_STATUS (*txrx_get_peer_extd_rate_link_stats) (struct cdp_soc_t *soc, uint8_t *mac_addr); + QDF_STATUS + (*get_pdev_obss_stats)(struct cdp_soc_t *soc, uint8_t pdev_id, + struct cdp_pdev_obss_pd_stats_tlv *buf); + QDF_STATUS (*clear_pdev_obss_pd_stats)(struct cdp_soc_t *soc, + uint8_t pdev_id); }; struct cdp_wds_ops { diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index bcbcf3b5fa..ac9ea4dc12 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -2245,6 +2245,116 @@ struct cdp_htt_tx_pdev_stats_cmn_tlv { uint32_t tx_active_dur_us_high; }; +#define DP_NUM_AC_WMM 4 + +struct cdp_pdev_obss_pd_stats_tlv { + struct cdp_htt_tlv_hdr tlv_hdr; + + uint32_t num_obss_tx_ppdu_success; + uint32_t num_obss_tx_ppdu_failure; + /** num_sr_tx_transmissions: + * Counter of TX done by aborting other BSS RX with spatial reuse + * (for cases where rx RSSI from other BSS is below the packet-detection + * threshold for doing spatial reuse) + */ + uint32_t num_sr_tx_transmissions; + /** + * Count the number of times the RSSI from an other-BSS signal + * is below the spatial reuse power threshold, thus providing an + * opportunity for spatial reuse since OBSS interference will be + * inconsequential. + */ + uint32_t num_spatial_reuse_opportunities; + /** + * Count of number of times OBSS frames were aborted and non-SRG + * opportunities were created. Non-SRG opportunities are created when + * incoming OBSS RSSI is lesser than the global configured non-SRG RSSI + * threshold and non-SRG OBSS color / non-SRG OBSS BSSID registers + * allow non-SRG TX. + */ + uint32_t num_non_srg_opportunities; + /** + * Count of number of times TX PPDU were transmitted using non-SRG + * opportunities created. Incoming OBSS frame RSSI is compared with per + * PPDU non-SRG RSSI threshold configured in each PPDU. If incoming OBSS + * RSSI < non-SRG RSSI threshold configured in each PPDU, then non-SRG + * tranmission happens. + */ + uint32_t num_non_srg_ppdu_tried; + /** + * Count of number of times non-SRG based TX transmissions were + * successful + */ + uint32_t num_non_srg_ppdu_success; + /** + * Count of number of times OBSS frames were aborted and SRG + * opportunities were created. Srg opportunities are created when + * incoming OBSS RSSI is less than the global configured SRG RSSI + * threshold and SRC OBSS color / SRG OBSS BSSID / SRG partial bssid / + * SRG BSS color bitmap registers allow SRG TX. + */ + uint32_t num_srg_opportunities; + /** + * Count of number of times TX PPDU were transmitted using SRG + * opportunities created. + * Incoming OBSS frame RSSI is compared with per PPDU SRG RSSI + * threshold configured in each PPDU. + * If incoming OBSS RSSI < SRG RSSI threshold configured in each PPDU, + * then SRG tranmission happens. + */ + uint32_t num_srg_ppdu_tried; + /** + * Count of number of times SRG based TX transmissions were successful + */ + uint32_t num_srg_ppdu_success; + /** + * Count of number of times PSR opportunities were created by aborting + * OBSS UL OFDMA HE-TB PPDU frame. HE-TB ppdu frames are aborted if the + * spatial reuse info in the OBSS trigger common field is set to allow + * PSR based spatial reuse. + */ + uint32_t num_psr_opportunities; + /** + * Count of number of times TX PPDU were transmitted using PSR + * opportunities created. + */ + uint32_t num_psr_ppdu_tried; + /** + * Count of number of times PSR based TX transmissions were successful. + */ + uint32_t num_psr_ppdu_success; + /** + * Count of number of times TX PPDU per access category were transmitted + * using non-SRG opportunities created. + */ + uint32_t num_non_srg_ppdu_tried_per_ac[DP_NUM_AC_WMM]; + /** + * Count of number of times non-SRG based TX transmissions per access + * category were successful + */ + uint32_t num_non_srg_ppdu_success_per_ac[DP_NUM_AC_WMM]; + /** + * Count of number of times TX PPDU per access category were transmitted + * using SRG opportunities created. + */ + uint32_t num_srg_ppdu_tried_per_ac[DP_NUM_AC_WMM]; + /** + * Count of number of times SRG based TX transmissions per access + * category were successful + */ + uint32_t num_srg_ppdu_success_per_ac[DP_NUM_AC_WMM]; + /** + * Count of number of times ppdu was flushed due to ongoing OBSS + * frame duration value lesser than minimum required frame duration. + */ + uint32_t num_obss_min_duration_check_flush_cnt; + /** + * Count of number of times ppdu was flushed due to ppdu duration + * exceeding aborted OBSS frame duration + */ + uint32_t num_sr_ppdu_abort_flush_cnt; +}; + struct cdp_htt_tx_pdev_stats_urrn_tlv_v { struct cdp_htt_tlv_hdr tlv_hdr; uint32_t urrn_stats[1]; /* HTT_TX_PDEV_MAX_URRN_STATS */ @@ -2376,6 +2486,7 @@ struct cdp_htt_tx_pdev_stats { struct cdp_htt_tx_pdev_stats_sifs_tlv_v sifs_tlv; struct cdp_htt_tx_pdev_stats_flush_tlv_v flush_tlv; struct cdp_htt_tx_pdev_stats_phy_err_tlv_v phy_err_tlv; + struct cdp_pdev_obss_pd_stats_tlv obss_pd_stats_tlv; }; struct cdp_htt_rx_soc_stats_t { diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 68bfeaf656..9411f6fab9 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -1863,6 +1863,26 @@ dp_htt_stats_sysfs_set_event(struct dp_soc *dp_soc, uint32_t *msg_word) } #endif /* WLAN_SYSFS_DP_STATS */ +/* dp_htt_set_pdev_obss_stats() - Function to set pdev obss stats. + * @pdev: dp pdev handle + * @tag_type: HTT TLV tag type + * @tag_buf: TLV buffer pointer + * + * Return: None + */ +static inline void +dp_htt_set_pdev_obss_stats(struct dp_pdev *pdev, uint32_t tag_type, + uint32_t *tag_buf) +{ + if (tag_type != HTT_STATS_PDEV_OBSS_PD_TAG) { + dp_err("Tag mismatch"); + return; + } + qdf_mem_copy(&pdev->stats.htt_tx_pdev_stats.obss_pd_stats_tlv, + tag_buf, sizeof(struct cdp_pdev_obss_pd_stats_tlv)); + qdf_event_set(&pdev->fw_obss_stats_event); +} + /** * dp_process_htt_stat_msg(): Process the list of buffers of HTT EXT stats * @htt_stats: htt stats info @@ -1992,6 +2012,11 @@ static inline void dp_process_htt_stat_msg(struct htt_stats_context *htt_stats, tlv_type, tlv_start); + if (cookie_msb & DBG_STATS_COOKIE_HTT_OBSS) + dp_htt_set_pdev_obss_stats(pdev, + tlv_type, + tlv_start); + msg_remain_len -= tlv_remain_len; msg_word = (uint32_t *) diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 93d167dccd..8b1c67fc7c 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -71,6 +71,9 @@ struct htt_dbgfs_cfg { /*Reserve for HTT Stats debugfs support: 5th bit */ #define DBG_SYSFS_STATS_COOKIE BIT(5) +/* Reserve for HTT Stats OBSS PD support: 6th bit */ +#define DBG_STATS_COOKIE_HTT_OBSS BIT(6) + /** * Bitmap of HTT PPDU TLV types for Default mode */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index aaac304958..4e22db5300 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -5927,6 +5927,7 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force) dp_pdev_bkp_stats_detach(pdev); qdf_event_destroy(&pdev->fw_peer_stats_event); qdf_event_destroy(&pdev->fw_stats_event); + qdf_event_destroy(&pdev->fw_obss_stats_event); if (pdev->sojourn_buf) qdf_nbuf_free(pdev->sojourn_buf); @@ -11460,6 +11461,95 @@ dp_txrx_stats_publish(struct cdp_soc_t *soc, uint8_t pdev_id, return TXRX_STATS_LEVEL; } +/* + * dp_get_obss_stats(): Get Pdev OBSS stats from Fw + * @soc: DP soc handle + * @pdev_id: id of DP_PDEV handle + * @buf: to hold pdev obss stats + * + * Return: status + */ +static QDF_STATUS +dp_get_obss_stats(struct cdp_soc_t *soc, uint8_t pdev_id, + struct cdp_pdev_obss_pd_stats_tlv *buf) +{ + struct cdp_txrx_stats_req req = {0}; + QDF_STATUS status; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return QDF_STATUS_E_INVAL; + + if (pdev->pending_fw_obss_stats_response) + return QDF_STATUS_E_AGAIN; + + pdev->pending_fw_obss_stats_response = true; + req.stats = (enum cdp_stats)HTT_DBG_EXT_STATS_PDEV_OBSS_PD_STATS; + req.cookie_val = DBG_STATS_COOKIE_HTT_OBSS; + qdf_event_reset(&pdev->fw_obss_stats_event); + status = dp_h2t_ext_stats_msg_send(pdev, req.stats, req.param0, + req.param1, req.param2, req.param3, + 0, req.cookie_val, 0); + if (QDF_IS_STATUS_ERROR(status)) { + pdev->pending_fw_obss_stats_response = false; + return status; + } + status = + qdf_wait_single_event(&pdev->fw_obss_stats_event, + DP_MAX_SLEEP_TIME); + + if (status != QDF_STATUS_SUCCESS) { + if (status == QDF_STATUS_E_TIMEOUT) + qdf_debug("TIMEOUT_OCCURS"); + pdev->pending_fw_obss_stats_response = false; + return QDF_STATUS_E_TIMEOUT; + } + qdf_mem_copy(buf, &pdev->stats.htt_tx_pdev_stats.obss_pd_stats_tlv, + sizeof(struct cdp_pdev_obss_pd_stats_tlv)); + pdev->pending_fw_obss_stats_response = false; + return status; +} + +/* + * dp_clear_pdev_obss_pd_stats(): Clear pdev obss stats + * @soc: DP soc handle + * @pdev_id: id of DP_PDEV handle + * + * Return: status + */ +static QDF_STATUS +dp_clear_pdev_obss_pd_stats(struct cdp_soc_t *soc, uint8_t pdev_id) +{ + struct cdp_txrx_stats_req req = {0}; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + uint32_t cookie_val = DBG_STATS_COOKIE_DEFAULT; + + if (!pdev) + return QDF_STATUS_E_INVAL; + + /* + * For HTT_DBG_EXT_STATS_RESET command, FW need to config + * from param0 to param3 according to below rule: + * + * PARAM: + * - config_param0 : start_offset (stats type) + * - config_param1 : stats bmask from start offset + * - config_param2 : stats bmask from start offset + 32 + * - config_param3 : stats bmask from start offset + 64 + */ + req.stats = (enum cdp_stats)HTT_DBG_EXT_STATS_RESET; + req.param0 = HTT_DBG_EXT_STATS_PDEV_OBSS_PD_STATS; + req.param1 = 0x00000001; + + return dp_h2t_ext_stats_msg_send(pdev, req.stats, req.param0, + req.param1, req.param2, req.param3, 0, + cookie_val, 0); +} + /** * dp_set_pdev_dscp_tid_map_wifi3(): update dscp tid map in pdev * @soc: soc handle @@ -13880,6 +13970,8 @@ static struct cdp_host_stats_ops dp_ops_host_stats = { #endif .txrx_get_peer_extd_rate_link_stats = dp_get_peer_extd_rate_link_stats, + .get_pdev_obss_stats = dp_get_obss_stats, + .clear_pdev_obss_pd_stats = dp_clear_pdev_obss_pd_stats, /* TODO */ }; @@ -16942,6 +17034,7 @@ static QDF_STATUS dp_pdev_init(struct cdp_soc_t *txrx_soc, qdf_event_create(&pdev->fw_peer_stats_event); qdf_event_create(&pdev->fw_stats_event); + qdf_event_create(&pdev->fw_obss_stats_event); pdev->num_tx_allowed = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 35174a5430..b9ec12f888 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -3058,6 +3058,12 @@ struct dp_pdev { /* qdf_event for fw_stats */ qdf_event_t fw_stats_event; + /* qdf_event for fw__obss_stats */ + qdf_event_t fw_obss_stats_event; + + /* To check if request is already sent for obss stats */ + bool pending_fw_obss_stats_response; + /* User configured max number of tx buffers */ uint32_t num_tx_allowed;