From 21af5ba8cfbcb69e0325216fab7a706a81c62e5a Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Mon, 24 Aug 2020 04:55:01 -0700 Subject: [PATCH] qcacmn: Add data structures for SWLM Add the necessary data structures for the software latency manager. Change-Id: Ibf55f0eef7ee6602b007de39a28f09c4622bd356 CRs-Fixed: 2769004 --- dp/wifi3.0/dp_internal.h | 30 ++++++++++ dp/wifi3.0/dp_main.c | 2 + dp/wifi3.0/dp_rx.c | 21 +++++++ dp/wifi3.0/dp_rx.h | 5 -- dp/wifi3.0/dp_tx.c | 20 +++++++ dp/wifi3.0/dp_types.h | 115 +++++++++++++++++++++++++++++++++++++ hal/wifi3.0/hal_api.h | 24 ++++++++ hal/wifi3.0/hal_internal.h | 1 + 8 files changed, 213 insertions(+), 5 deletions(-) diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 9330b77f5b..ede44a9c66 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -386,6 +386,11 @@ while (0) #define DP_TX_HIST_STATS_PER_PDEV() #endif /* DISABLE_DP_STATS */ +#define FRAME_MASK_IPV4_ARP 1 +#define FRAME_MASK_IPV4_DHCP 2 +#define FRAME_MASK_IPV4_EAPOL 4 +#define FRAME_MASK_IPV6_DHCP 8 + #ifdef QCA_SUPPORT_PEER_ISOLATION #define dp_get_peer_isolation(_peer) ((_peer)->isolation) @@ -2393,4 +2398,29 @@ dp_pdev_htt_stats_dbgfs_deinit(struct dp_pdev *pdev) { } #endif /* HTT_STATS_DEBUGFS_SUPPORT */ + +#ifndef WLAN_DP_FEATURE_SW_LATENCY_MGR +/** + * dp_soc_swlm_attach() - attach the software latency manager resources + * @soc: Datapath global soc handle + * + * Returns: QDF_STATUS + */ +static inline QDF_STATUS dp_soc_swlm_attach(struct dp_soc *soc) +{ + return QDF_STATUS_SUCCESS; +} + +/** + * dp_soc_swlm_detach() - detach the software latency manager resources + * @soc: Datapath global soc handle + * + * Returns: QDF_STATUS + */ +static inline QDF_STATUS dp_soc_swlm_detach(struct dp_soc *soc) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* !WLAN_DP_FEATURE_SW_LATENCY_MGR */ + #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 43ac1c8bc1..46fecefc5c 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4590,6 +4590,7 @@ static void dp_soc_detach(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; + dp_soc_swlm_detach(soc); dp_soc_tx_desc_sw_pools_free(soc); dp_soc_srng_free(soc); dp_hw_link_desc_ring_free(soc); @@ -11570,6 +11571,7 @@ dp_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, goto fail5; } + dp_soc_swlm_attach(soc); dp_soc_set_interrupt_mode(soc); dp_soc_set_def_pdev(soc); diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index af1b429f13..efc0177a48 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2060,6 +2060,26 @@ dp_rx_ring_record_entry(struct dp_soc *soc, uint8_t ring_num, } #endif +#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR +/** + * dp_rx_update_stats() - Update soc level rx packet count + * @soc: DP soc handle + * @nbuf: nbuf received + * + * Returns: none + */ +static inline void dp_rx_update_stats(struct dp_soc *soc, + qdf_nbuf_t nbuf) +{ + DP_STATS_INC_PKT(soc, rx.ingress, 1, + QDF_NBUF_CB_RX_PKT_LEN(nbuf)); +} +#else +static inline void dp_rx_update_stats(struct dp_soc *soc, + qdf_nbuf_t nbuf) +{ +} +#endif /** * dp_rx_process() - Brain of the Rx processing functionality * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) @@ -2692,6 +2712,7 @@ done: dp_rx_fill_gro_info(soc, rx_tlv_hdr, nbuf, &rx_ol_pkt_cnt); + dp_rx_update_stats(soc, nbuf); DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, nbuf); diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index b240bb2aa7..b504fa2ed3 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -167,11 +167,6 @@ struct dp_rx_desc { (((_cookie) & RX_DESC_COOKIE_INDEX_MASK) >> \ RX_DESC_COOKIE_INDEX_SHIFT) -#define FRAME_MASK_IPV4_ARP 1 -#define FRAME_MASK_IPV4_DHCP 2 -#define FRAME_MASK_IPV4_EAPOL 4 -#define FRAME_MASK_IPV6_DHCP 8 - #define dp_rx_add_to_free_desc_list(head, tail, new) \ __dp_rx_add_to_free_desc_list(head, tail, new, __func__) diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 12bc815fc7..85983986c3 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1130,6 +1130,25 @@ static void dp_tx_raw_prepare_unset(struct dp_soc *soc, #define dp_vdev_peer_stats_update_protocol_cnt_tx(vdev_hdl, skb) #endif +#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR +/** + * dp_tx_update_stats() - Update soc level tx stats + * @soc: DP soc handle + * @nbuf: packet being transmitted + * + * Returns: none + */ +static inline void dp_tx_update_stats(struct dp_soc *soc, + qdf_nbuf_t nbuf) +{ + DP_STATS_INC_PKT(soc, tx.egress, 1, qdf_nbuf_len(nbuf)); +} +#else +static inline void dp_tx_update_stats(struct dp_soc *soc, + qdf_nbuf_t nbuf) +{ +} +#endif /** * dp_tx_hw_enqueue() - Enqueue to TCL HW for transmit * @soc: DP Soc Handle @@ -1273,6 +1292,7 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf); hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc); DP_STATS_INC_PKT(vdev, tx_i.processed, 1, tx_desc->length); + dp_tx_update_stats(soc, tx_desc->nbuf); status = QDF_STATUS_SUCCESS; ring_access_fail: diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 49c6856225..03d78bb0a4 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -813,6 +813,8 @@ struct dp_soc_stats { /* SOC level TX stats */ struct { + /* Total packets transmitted */ + struct cdp_pkt_info egress; /* packets dropped on tx because of no peer */ struct cdp_pkt_info tx_invalid_peer; /* descriptors in each tcl ring */ @@ -835,6 +837,8 @@ struct dp_soc_stats { /* SOC level RX stats */ struct { + /* Total rx packets count */ + struct cdp_pkt_info ingress; /* Rx errors */ /* Total Packets in Rx Error ring */ uint32_t err_ring_pkts; @@ -1121,6 +1125,113 @@ struct dp_last_op_info { struct hal_buf_info reo_reinject_link_desc; }; +#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR + +/** + * struct dp_swlm_tcl_data - params for tcl register write coalescing + * descision making + * @nbuf: TX packet + * @tid: tid for transmitting the current packet + * + * This structure contains the information required by the software + * latency manager to decide on whether to coalesc the current TCL + * register write or not. + */ +struct dp_swlm_tcl_data { + qdf_nbuf_t nbuf; + uint8_t tid; +}; + +/** + * union swlm_data - SWLM query data + * @tcl_data: data for TCL query in SWLM + */ +union swlm_data { + struct dp_swlm_tcl_data *tcl_data; +}; + +/** + * struct dp_swlm_ops - SWLM ops + * @tcl_should_coalesc: Should the current TCL register write be coalesced + * or not + */ +struct dp_swlm_ops { + int (*tcl_should_coalesc)(struct dp_soc *soc, + struct dp_swlm_tcl_data *tcl_data); +}; + +/** + * struct dp_swlm_stats - Stats for Software Latency manager. + * @tcl.timer_flush_success: Num TCL HP writes success from timer context + * @tcl.timer_flush_fail: Num TCL HP writes failure from timer context + * @tcl.tid_fail: Num TCL register write coalescing skips, since the pkt + * was being transmitted on a TID above coalescing threshold + * @tcl.sp_frames: Num TCL register write coalescing skips, since the pkt + * being transmitted was a special frame + * @tcl.bytes_thresh_reached: Num TCL HP writes flush after the coalescing + * bytes threshold was reached + * @tcl.time_thresh_reached: Num TCL HP writes flush after the coalescing + * session time expired + * @tcl.tput_criteria_fail: Num TCL HP writes coalescing fails, since the + * throughput did not meet session threshold + */ +struct dp_swlm_stats { + struct { + uint32_t timer_flush_success; + uint32_t timer_flush_fail; + uint32_t tid_fail; + uint32_t sp_frames; + uint32_t bytes_thresh_reached; + uint32_t time_thresh_reached; + uint32_t tput_criteria_fail; + } tcl; +}; + +/** + * struct dp_swlm_params: Parameters for different modules in the + * Software latency manager. + * @tcl.flush_timer: Timer for flushing the coalesced TCL HP writes + * @tcl.rx_traffic_thresh: Threshold for RX traffic, to begin TCL register + * write coalescing + * @tcl.tx_traffic_thresh: Threshold for TX traffic, to begin TCL register + * write coalescing + * @tcl.sampling_time: Sampling time to test the throughput threshold + * @tcl.sampling_session_tx_bytes: Num bytes transmitted in the sampling time + * @tcl.bytes_flush_thresh: Bytes threshold to flush the TCL HP register write + * @tcl.time_flush_thresh: Time threshold to flush the TCL HP register write + * @tcl.tx_thresh_multiplier: Multiplier to deduce the bytes threshold after + * which the TCL HP register is written, thereby + * ending the coalescing. + */ +struct dp_swlm_params { + struct { + qdf_timer_t flush_timer; + uint32_t rx_traffic_thresh; + uint32_t tx_traffic_thresh; + uint32_t sampling_time; + uint32_t sampling_session_tx_bytes; + uint32_t bytes_flush_thresh; + uint32_t time_flush_thresh; + uint32_t tx_thresh_multiplier; + } tcl; +}; + +/** + * struct dp_swlm - Software latency manager context + * @ops: SWLM ops pointers + * @is_enabled: SWLM enabled/disabled + * @stats: SWLM stats + * @params: SWLM SRNG params + * @tcl_flush_timer: flush timer for TCL register writes + */ +struct dp_swlm { + struct dp_swlm_ops *ops; + uint8_t is_enabled; + struct dp_swlm_stats stats; + struct dp_swlm_params params; +}; +#endif + /* SOC level structure for data path */ struct dp_soc { /** @@ -1528,6 +1639,10 @@ struct dp_soc { qdf_spinlock_t inactive_vdev_list_lock; /* lock to protect vdev_id_map table*/ qdf_spinlock_t vdev_map_lock; + +#ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR + struct dp_swlm swlm; +#endif }; #ifdef IPA_OFFLOAD diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 0f1167b941..3ffa518d77 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -984,6 +984,30 @@ hal_srng_access_start_unlocked(hal_soc_handle_t hal_soc_hdl, return 0; } +/** + * hal_srng_try_access_start - Try to start (locked) ring access + * + * @hal_soc: Opaque HAL SOC handle + * @hal_ring_hdl: Ring pointer (Source or Destination ring) + * + * Return: 0 on success; error on failure + */ +static inline int hal_srng_try_access_start(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + + if (qdf_unlikely(!hal_ring_hdl)) { + qdf_print("Error: Invalid hal_ring\n"); + return -EINVAL; + } + + if (!SRNG_TRY_LOCK(&(srng->lock))) + return -EINVAL; + + return hal_srng_access_start_unlocked(hal_soc_hdl, hal_ring_hdl); +} + /** * hal_srng_access_start - Start (locked) ring access * diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 19f24ad65f..6745a52a8d 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -209,6 +209,7 @@ enum hal_srng_dir { #define hal_srng_lock_t qdf_spinlock_t #define SRNG_LOCK_INIT(_lock) qdf_spinlock_create(_lock) #define SRNG_LOCK(_lock) qdf_spin_lock_bh(_lock) +#define SRNG_TRY_LOCK(_lock) qdf_spin_trylock_bh(_lock) #define SRNG_UNLOCK(_lock) qdf_spin_unlock_bh(_lock) #define SRNG_LOCK_DESTROY(_lock) qdf_spinlock_destroy(_lock)