Просмотр исходного кода

qcacmn: Add data structures for SWLM

Add the necessary data structures for the
software latency manager.

Change-Id: Ibf55f0eef7ee6602b007de39a28f09c4622bd356
CRs-Fixed: 2769004
Rakesh Pillai 4 лет назад
Родитель
Сommit
21af5ba8cf

+ 30 - 0
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_ */

+ 2 - 0
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);
 

+ 21 - 0
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);

+ 0 - 5
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__)
 

+ 20 - 0
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:

+ 115 - 0
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

+ 24 - 0
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
  *

+ 1 - 0
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)