diff --git a/dp/cmn_dp_api/dp_ratetable.c b/dp/cmn_dp_api/dp_ratetable.c index bf3b4cbfbc..2a4e260513 100644 --- a/dp/cmn_dp_api/dp_ratetable.c +++ b/dp/cmn_dp_api/dp_ratetable.c @@ -17,6 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include #include "dp_ratetable.h" #include "qdf_module.h" #include "cdp_txrx_mon_struct.h" diff --git a/dp/inc/cdp_txrx_misc.h b/dp/inc/cdp_txrx_misc.h index 88d198c871..9411fb460f 100644 --- a/dp/inc/cdp_txrx_misc.h +++ b/dp/inc/cdp_txrx_misc.h @@ -994,4 +994,57 @@ cdp_set_peer_txq_flush_config(ol_txrx_soc_handle soc, uint8_t vdev_id, return 0; } #endif /* WLAN_FEATURE_PEER_TXQ_FLUSH_CONF */ +#ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER +/** + * cdp_set_bus_vote_lvl() - have a vote on bus bandwidth lvl + * @soc: datapath soc handle + * @high: whether TPUT level is high or not + * + * Return: void + */ +static inline void +cdp_set_bus_vote_lvl_high(ol_txrx_soc_handle soc, bool high) +{ + if (!soc || !soc->ops || !soc->ops->misc_ops || + !soc->ops->misc_ops->set_bus_vote_lvl_high) { + dp_cdp_debug("Invalid Instance:"); + return; + } + + soc->ops->misc_ops->set_bus_vote_lvl_high(soc, high); +} + +/** + * cdp_get_bus_vote_lvl() - get bus bandwidth lvl from dp + * @soc: datapath soc handle + * + * Return: bool, whether TPUT level is high or not + */ +static inline bool +cdp_get_bus_lvl_high(ol_txrx_soc_handle soc) +{ + if (!soc || !soc->ops || !soc->ops->misc_ops || + !soc->ops->misc_ops->get_bus_vote_lvl_high) { + dp_cdp_debug("Invalid Instance:"); + return false; + } + + return soc->ops->misc_ops->get_bus_vote_lvl_high(soc); +} +#else +static inline void +cdp_set_bus_vote_lvl_high(ol_txrx_soc_handle soc, bool high) +{ +} + +static inline bool +cdp_get_bus_lvl_high(ol_txrx_soc_handle soc) +{ + /* + * default bus lvl is high to + * make sure not affect tput + */ + return true; +} +#endif #endif /* _CDP_TXRX_MISC_H_ */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index d017397e68..1751ba3b7c 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -1513,6 +1513,10 @@ struct ol_if_ops { * @set_tx_flush_pending: Configures the ac/tid to be flushed and policy * to flush. * + * set_bus_vote_lvl_high: The bus lvl is set to high or low based on tput + * get_bus_vote_lvl_high: Get bus lvl to determine whether or not get + * rx rate stats + * * Function pointers for miscellaneous soc/pdev/vdev related operations. */ struct cdp_misc_ops { @@ -1610,6 +1614,10 @@ struct cdp_misc_ops { uint8_t ac, uint32_t tid, enum cdp_peer_txq_flush_policy policy); #endif +#ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER + void (*set_bus_vote_lvl_high)(struct cdp_soc_t *soc_hdl, bool high); + bool (*get_bus_vote_lvl_high)(struct cdp_soc_t *soc_hdl); +#endif }; /** diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index b5517bc4af..ddd07bcc6a 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -13591,6 +13591,37 @@ void dp_deregister_packetdump_callback(struct cdp_soc_t *soc_hdl, } #endif +#ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER +/** + * dp_set_bus_vote_lvl_high() - Take a vote on bus bandwidth from dp + * @soc_hdl: Datapath soc handle + * @high: whether the bus bw is high or not + * + * Return: void + */ +static void +dp_set_bus_vote_lvl_high(ol_txrx_soc_handle soc_hdl, bool high) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + + soc->high_throughput = high; +} + +/** + * dp_get_bus_vote_lvl_high() - get bus bandwidth vote to dp + * @soc_hdl: Datapath soc handle + * + * Return: bool + */ +static bool +dp_get_bus_vote_lvl_high(ol_txrx_soc_handle soc_hdl) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + + return soc->high_throughput; +} +#endif + #ifdef DP_PEER_EXTENDED_API static struct cdp_misc_ops dp_ops_misc = { #ifdef FEATURE_WLAN_TDLS @@ -13631,6 +13662,10 @@ static struct cdp_misc_ops dp_ops_misc = { .register_pktdump_cb = dp_register_packetdump_callback, .unregister_pktdump_cb = dp_deregister_packetdump_callback, #endif +#ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER + .set_bus_vote_lvl_high = dp_set_bus_vote_lvl_high, + .get_bus_vote_lvl_high = dp_get_bus_vote_lvl_high, +#endif }; #endif @@ -15532,6 +15567,8 @@ static void dp_soc_cfg_init(struct dp_soc *soc) soc->wlan_cfg_ctx->rxdma1_enable = 0; soc->wlan_cfg_ctx->num_rxdma_dst_rings_per_pdev = 1; + /* use only MAC0 status ring */ + soc->wlan_cfg_ctx->num_rxdma_status_rings_per_pdev = 1; break; case TARGET_TYPE_QCA8074: wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, true); diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 7a68b374b6..912a354cd1 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -39,6 +39,9 @@ #ifdef FEATURE_WDS #include "dp_txrx_wds.h" #endif +#ifdef DP_RATETABLE_SUPPORT +#include "dp_ratetable.h" +#endif #ifdef DUP_RX_DESC_WAR void dp_rx_dump_info_and_assert(struct dp_soc *soc, @@ -2073,6 +2076,70 @@ QDF_STATUS dp_rx_eapol_deliver_to_stack(struct dp_soc *soc, #define dp_rx_msdu_stats_update_prot_cnts(vdev_hdl, nbuf, txrx_peer) #endif +#ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER +/** + * dp_rx_rates_stats_update() - update rate stats + * from rx msdu. + * @soc: datapath soc handle + * @nbuf: received msdu buffer + * @rx_tlv_hdr: rx tlv header + * @txrx_peer: datapath txrx_peer handle + * @sgi: Short Guard Interval + * @mcs: Modulation and Coding Set + * @nss: Number of Spatial Streams + * @bw: BandWidth + * @pkt_type: Corresponds to preamble + * + * To be precisely record rates, following factors are considered: + * Exclude specific frames, ARP, DHCP, ssdp, etc. + * Make sure to affect rx throughput as least as possible. + * + * Return: void + */ +static void +dp_rx_rates_stats_update(struct dp_soc *soc, qdf_nbuf_t nbuf, + uint8_t *rx_tlv_hdr, struct dp_txrx_peer *txrx_peer, + uint32_t sgi, uint32_t mcs, + uint32_t nss, uint32_t bw, uint32_t pkt_type) +{ + uint32_t rix; + uint16_t ratecode; + uint32_t avg_rx_rate; + uint32_t ratekbps; + enum cdp_punctured_modes punc_mode = NO_PUNCTURE; + + if (soc->high_throughput || + dp_rx_data_is_specific(soc->hal_soc, rx_tlv_hdr, nbuf)) { + return; + } + + DP_PEER_EXTD_STATS_UPD(txrx_peer, rx.rx_rate, mcs); + + /* here pkt_type corresponds to preamble */ + ratekbps = dp_getrateindex(sgi, + mcs, + nss, + pkt_type, + bw, + punc_mode, + &rix, + &ratecode); + DP_PEER_EXTD_STATS_UPD(txrx_peer, rx.last_rx_rate, ratekbps); + avg_rx_rate = + dp_ath_rate_lpf(txrx_peer->stats.extd_stats.rx.avg_rx_rate, + ratekbps); + DP_PEER_EXTD_STATS_UPD(txrx_peer, rx.avg_rx_rate, avg_rx_rate); +} +#else +static void +dp_rx_rates_stats_update(struct dp_soc *soc, qdf_nbuf_t nbuf, + uint8_t *rx_tlv_hdr, struct dp_txrx_peer *txrx_peer, + uint32_t sgi, uint32_t mcs, + uint32_t nss, uint32_t bw, uint32_t pkt_type) +{ +} +#endif /* FEATURE_RX_LINKSPEED_ROAM_TRIGGER */ + #ifndef QCA_ENHANCED_STATS_SUPPORT /** * dp_rx_msdu_extd_stats_update(): Update Rx extended path stats for peer @@ -2141,6 +2208,9 @@ void dp_rx_msdu_extd_stats_update(struct dp_soc *soc, qdf_nbuf_t nbuf, DP_PEER_EXTD_STATS_INC(txrx_peer, rx.pkt_type[pkt_type].mcs_count[dst_mcs_idx], 1); + + dp_rx_rates_stats_update(soc, nbuf, rx_tlv_hdr, txrx_peer, + sgi, mcs, nss, bw, pkt_type); } #else static inline diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index e87f6ee8ef..52f66b5215 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -279,6 +279,64 @@ bool dp_rx_deliver_special_frame(struct dp_soc *soc, struct dp_txrx_peer *peer, } #endif +#ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER +/** + * dp_rx_data_is_specific() - Used to exclude specific frames + * not practical for getting rx + * stats like rate, mcs, nss, etc. + * + * @hal-soc_hdl: soc handler + * @rx_tlv_hdr: rx tlv header + * @nbuf: RX skb pointer + * + * Return: true - a specific frame not suitable + * for getting rx stats from it. + * false - a common frame suitable for + * getting rx stats from it. + */ +static inline +bool dp_rx_data_is_specific(hal_soc_handle_t hal_soc_hdl, + uint8_t *rx_tlv_hdr, + qdf_nbuf_t nbuf) +{ + if (qdf_unlikely(qdf_nbuf_is_da_mcbc(nbuf))) + return true; + + if (!hal_rx_tlv_first_mpdu_get(hal_soc_hdl, rx_tlv_hdr)) + return true; + + if (!hal_rx_msdu_end_first_msdu_get(hal_soc_hdl, rx_tlv_hdr)) + return true; + + /* ARP, EAPOL is neither IPV6 ETH nor IPV4 ETH from L3 level */ + if (qdf_likely(hal_rx_tlv_l3_type_get(hal_soc_hdl, rx_tlv_hdr) == + QDF_NBUF_TRAC_IPV4_ETH_TYPE)) { + if (qdf_nbuf_is_ipv4_dhcp_pkt(nbuf)) + return true; + } else if (qdf_likely(hal_rx_tlv_l3_type_get(hal_soc_hdl, rx_tlv_hdr) == + QDF_NBUF_TRAC_IPV6_ETH_TYPE)) { + if (qdf_nbuf_is_ipv6_dhcp_pkt(nbuf)) + return true; + } else { + return true; + } + return false; +} +#else +static inline +bool dp_rx_data_is_specific(hal_soc_handle_t hal_soc_hdl, + uint8_t *rx_tlv_hdr, + qdf_nbuf_t nbuf) + +{ + /* + * default return is true to make sure that rx stats + * will not be handled when this feature is disabled + */ + return true; +} +#endif /* FEATURE_RX_LINKSPEED_ROAM_TRIGGER */ + #ifndef QCA_HOST_MODE_WIFI_DISABLED #ifdef DP_RX_DISABLE_NDI_MDNS_FORWARDING static inline diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index e3f6c69aa8..105e10c0b0 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -2441,6 +2441,10 @@ struct dp_soc { /* PPDU to link_id mapping parameters */ uint8_t link_id_offset; uint8_t link_id_bits; +#ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER + /* A flag using to decide the switch of rx link speed */ + bool high_throughput; +#endif }; #ifdef IPA_OFFLOAD