1 /*
2 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #ifndef _WLAN_DP_SWLM_H_
19 #define _WLAN_DP_SWLM_H_
20
21 #ifdef WLAN_DP_FEATURE_SW_LATENCY_MGR
22
23 #define DP_SWLM_TCL_TPUT_PASS_THRESH 3
24
25 #define DP_SWLM_TCL_RX_TRAFFIC_THRESH 50
26 #define DP_SWLM_TCL_TX_TRAFFIC_THRESH 50
27 #define DP_SWLM_TCL_TX_PKT_THRESH 2
28
29 /* Traffic test time is in us */
30 #define DP_SWLM_TCL_TRAFFIC_SAMPLING_TIME 250
31 #define DP_SWLM_TCL_TIME_FLUSH_THRESH 1000
32 #define DP_SWLM_TCL_TX_THRESH_MULTIPLIER 2
33
34 /* Inline Functions */
35
36 /**
37 * dp_tx_is_special_frame() - check if this TX frame is a special frame.
38 * @nbuf: TX skb pointer
39 * @frame_mask: the mask for required special frames
40 *
41 * Check if TX frame is a required special frame.
42 *
43 * Returns: true, if this frame is a needed special frame,
44 * false, otherwise
45 */
46 static inline
dp_tx_is_special_frame(qdf_nbuf_t nbuf,uint32_t frame_mask)47 bool dp_tx_is_special_frame(qdf_nbuf_t nbuf, uint32_t frame_mask)
48 {
49 if (((frame_mask & FRAME_MASK_IPV4_ARP) &&
50 qdf_nbuf_is_ipv4_arp_pkt(nbuf)) ||
51 ((frame_mask & FRAME_MASK_IPV4_DHCP) &&
52 qdf_nbuf_is_ipv4_dhcp_pkt(nbuf)) ||
53 ((frame_mask & FRAME_MASK_IPV4_EAPOL) &&
54 qdf_nbuf_is_ipv4_eapol_pkt(nbuf)) ||
55 ((frame_mask & FRAME_MASK_IPV6_DHCP) &&
56 qdf_nbuf_is_ipv6_dhcp_pkt(nbuf)))
57 return true;
58
59 return false;
60 }
61
62 /**
63 * dp_swlm_tcl_reset_session_data() - Reset the TCL coalescing session data
64 * @soc: DP soc handle
65 * @ring_id: TCL ring id
66 *
67 * Returns QDF_STATUS
68 */
69 static inline QDF_STATUS
dp_swlm_tcl_reset_session_data(struct dp_soc * soc,uint8_t ring_id)70 dp_swlm_tcl_reset_session_data(struct dp_soc *soc, uint8_t ring_id)
71 {
72 struct dp_swlm_params *params = &soc->swlm.params;
73
74 params->tcl[ring_id].coalesce_end_time = qdf_get_log_timestamp_usecs() +
75 params->time_flush_thresh;
76 params->tcl[ring_id].bytes_coalesced = 0;
77 params->tcl[ring_id].bytes_flush_thresh =
78 params->tcl[ring_id].sampling_session_tx_bytes *
79 params->tx_thresh_multiplier;
80 qdf_timer_sync_cancel(¶ms->tcl[ring_id].flush_timer);
81
82 return QDF_STATUS_SUCCESS;
83 }
84
85 /**
86 * dp_swlm_tcl_pre_check() - Pre checks for current packet to be transmitted
87 * @soc: Datapath soc handle
88 * @tcl_data: tcl swlm data
89 *
90 * Returns: QDF_STATUS_SUCCESS, if all pre-check conditions pass
91 * QDF_STATUS_E_FAILURE, otherwise
92 */
93 static inline QDF_STATUS
dp_swlm_tcl_pre_check(struct dp_soc * soc,struct dp_swlm_tcl_data * tcl_data)94 dp_swlm_tcl_pre_check(struct dp_soc *soc,
95 struct dp_swlm_tcl_data *tcl_data)
96 {
97 struct dp_swlm *swlm = &soc->swlm;
98 uint32_t frame_mask = FRAME_MASK_IPV4_ARP | FRAME_MASK_IPV4_DHCP |
99 FRAME_MASK_IPV4_EAPOL | FRAME_MASK_IPV6_DHCP;
100
101 if (tcl_data->tid > DP_VO_TID) {
102 DP_STATS_INC(swlm, tcl[tcl_data->ring_id].tid_fail, 1);
103 goto fail;
104 }
105
106 if (dp_tx_is_special_frame(tcl_data->nbuf, frame_mask)) {
107 DP_STATS_INC(swlm, tcl[tcl_data->ring_id].sp_frames, 1);
108 goto fail;
109 }
110
111 if (tcl_data->num_ll_connections) {
112 DP_STATS_INC(swlm, tcl[tcl_data->ring_id].ll_connection, 1);
113 goto fail;
114 }
115
116 return QDF_STATUS_SUCCESS;
117
118 fail:
119 return QDF_STATUS_E_FAILURE;
120 }
121
122 /**
123 * dp_swlm_query_policy() - apply software latency policy based on ring type.
124 * @soc: Datapath global soc handle
125 * @ring_type: SRNG type
126 * @query_data: private data for the query corresponding to the ring type
127 *
128 * Returns: 1, if policy is to be applied
129 * 0, if policy is not to be applied
130 */
dp_swlm_query_policy(struct dp_soc * soc,int ring_type,union swlm_data query_data)131 static inline int dp_swlm_query_policy(struct dp_soc *soc, int ring_type,
132 union swlm_data query_data)
133 {
134 struct dp_swlm *swlm = &soc->swlm;
135
136 switch (ring_type) {
137 case TCL_DATA:
138 return swlm->ops->tcl_wr_coalesce_check(soc,
139 query_data.tcl_data);
140 default:
141 dp_err("Ring type %d not supported by SW latency manager",
142 ring_type);
143 break;
144 }
145
146 return 0;
147 }
148
149 /* Function Declarations */
150
151 /**
152 * dp_soc_swlm_attach() - attach the software latency manager resources
153 * @soc: Datapath global soc handle
154 *
155 * Returns: QDF_STATUS
156 */
157 QDF_STATUS dp_soc_swlm_attach(struct dp_soc *soc);
158
159 /**
160 * dp_soc_swlm_detach() - detach the software latency manager resources
161 * @soc: Datapath global soc handle
162 *
163 * Returns: QDF_STATUS
164 */
165 QDF_STATUS dp_soc_swlm_detach(struct dp_soc *soc);
166
167 /**
168 * dp_print_swlm_stats() - Print the SWLM stats
169 * @soc: Datapath soc handle
170 *
171 * Returns: QDF_STATUS
172 */
173 QDF_STATUS dp_print_swlm_stats(struct dp_soc *soc);
174
175 #endif /* WLAN_DP_FEATURE_SW_LATENCY_MGR */
176
177 #endif
178