1 /*
2  * Copyright (c) 2016-2019,2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: cdp_txrx_flow_ctrl_legacy.h
22  * Define the host data path legacy flow control API functions
23  */
24 #ifndef _CDP_TXRX_FC_LEG_H_
25 #define _CDP_TXRX_FC_LEG_H_
26 #include <cdp_txrx_mob_def.h>
27 #include "cdp_txrx_handle.h"
28 #include <cdp_txrx_cmn.h>
29 #ifdef QCA_HL_NETDEV_FLOW_CONTROL
30 
31 /**
32  * cdp_hl_fc_register() - Register HL flow control callback.
33  * @soc: data path soc handle
34  * @pdev_id: datapath pdev identifier
35  * @flowcontrol: callback function pointer to stop/start OS netdev queues
36  *
37  * Register flow control callback.
38  *
39  * Return: 0 for success
40  */
41 static inline int
cdp_hl_fc_register(ol_txrx_soc_handle soc,uint8_t pdev_id,tx_pause_callback flowcontrol)42 cdp_hl_fc_register(ol_txrx_soc_handle soc, uint8_t pdev_id,
43 		   tx_pause_callback flowcontrol)
44 {
45 	if (!soc || !soc->ops) {
46 		dp_cdp_debug("invalid instance");
47 		QDF_BUG(0);
48 		return -EINVAL;
49 	}
50 
51 	if (!soc->ops->l_flowctl_ops ||
52 	    !soc->ops->l_flowctl_ops->register_tx_flow_control)
53 		return -EINVAL;
54 
55 	return soc->ops->l_flowctl_ops->register_tx_flow_control(soc, pdev_id,
56 								 flowcontrol);
57 }
58 
cdp_hl_fc_set_td_limit(ol_txrx_soc_handle soc,uint8_t vdev_id,uint32_t chan_freq)59 static inline int cdp_hl_fc_set_td_limit(ol_txrx_soc_handle soc,
60 					 uint8_t vdev_id, uint32_t chan_freq)
61 {
62 	if (!soc->ops->l_flowctl_ops->set_vdev_tx_desc_limit)
63 		return 0;
64 
65 	return soc->ops->l_flowctl_ops->set_vdev_tx_desc_limit(soc, vdev_id,
66 							       chan_freq);
67 }
68 
cdp_hl_fc_set_os_queue_status(ol_txrx_soc_handle soc,uint8_t vdev_id,enum netif_action_type action)69 static inline int cdp_hl_fc_set_os_queue_status(ol_txrx_soc_handle soc,
70 						uint8_t vdev_id,
71 					    enum netif_action_type action)
72 {
73 	if (!soc->ops->l_flowctl_ops->set_vdev_os_queue_status)
74 		return -EINVAL;
75 
76 	return soc->ops->l_flowctl_ops->set_vdev_os_queue_status(soc,
77 								 vdev_id,
78 								 action);
79 }
80 #else
81 static inline int
cdp_hl_fc_register(ol_txrx_soc_handle soc,uint8_t pdev_id,tx_pause_callback flowcontrol)82 cdp_hl_fc_register(ol_txrx_soc_handle soc, uint8_t pdev_id,
83 		   tx_pause_callback flowcontrol)
84 {
85 	return 0;
86 }
87 
cdp_hl_fc_set_td_limit(ol_txrx_soc_handle soc,uint8_t vdev_id,uint32_t chan_freq)88 static inline int cdp_hl_fc_set_td_limit(ol_txrx_soc_handle soc,
89 					 uint8_t vdev_id, uint32_t chan_freq)
90 {
91 	return 0;
92 }
93 
cdp_hl_fc_set_os_queue_status(ol_txrx_soc_handle soc,uint8_t vdev_id,enum netif_action_type action)94 static inline int cdp_hl_fc_set_os_queue_status(ol_txrx_soc_handle soc,
95 						uint8_t vdev_id,
96 						enum netif_action_type action)
97 {
98 	return 0;
99 }
100 
101 #endif /* QCA_HL_NETDEV_FLOW_CONTROL */
102 
103 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
104 /**
105  * cdp_fc_register() - Register flow control callback function pointer
106  * @soc: data path soc handle
107  * @vdev_id: virtual interface id to register flow control
108  * @flowcontrol: callback function pointer
109  * @osif_fc_ctx: client context pointer
110  * @flow_control_is_pause: is vdev paused by flow control
111  *
112  * Register flow control callback function pointer and client context pointer
113  *
114  * Return: 0 success
115  */
116 static inline int
cdp_fc_register(ol_txrx_soc_handle soc,uint8_t vdev_id,ol_txrx_tx_flow_control_fp flowcontrol,void * osif_fc_ctx,ol_txrx_tx_flow_control_is_pause_fp flow_control_is_pause)117 cdp_fc_register(ol_txrx_soc_handle soc, uint8_t vdev_id,
118 		ol_txrx_tx_flow_control_fp flowcontrol, void *osif_fc_ctx,
119 		ol_txrx_tx_flow_control_is_pause_fp flow_control_is_pause)
120 {
121 	if (!soc || !soc->ops) {
122 		dp_cdp_debug("invalid instance");
123 		QDF_BUG(0);
124 		return 0;
125 	}
126 
127 	if (!soc->ops->l_flowctl_ops ||
128 	    !soc->ops->l_flowctl_ops->register_tx_flow_control)
129 		return 0;
130 
131 	return soc->ops->l_flowctl_ops->register_tx_flow_control(
132 			soc, vdev_id, flowcontrol, osif_fc_ctx,
133 			flow_control_is_pause);
134 }
135 #else
136 static inline int
cdp_fc_register(ol_txrx_soc_handle soc,uint8_t vdev_id,ol_txrx_tx_flow_control_fp flowcontrol,void * osif_fc_ctx,ol_txrx_tx_flow_control_is_pause_fp flow_control_is_pause)137 cdp_fc_register(ol_txrx_soc_handle soc, uint8_t vdev_id,
138 		ol_txrx_tx_flow_control_fp flowcontrol, void *osif_fc_ctx,
139 		ol_txrx_tx_flow_control_is_pause_fp flow_control_is_pause)
140 {
141 	return 0;
142 }
143 #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
144 /**
145  * cdp_fc_deregister() - remove flow control instance
146  * @soc: data path soc handle
147  * @vdev_id: virtual interface id to register flow control
148  *
149  * remove flow control instance
150  *
151  * Return: 0 success
152  */
153 static inline int
cdp_fc_deregister(ol_txrx_soc_handle soc,uint8_t vdev_id)154 cdp_fc_deregister(ol_txrx_soc_handle soc, uint8_t vdev_id)
155 {
156 	if (!soc || !soc->ops) {
157 		dp_cdp_debug("invalid instance");
158 		QDF_BUG(0);
159 		return 0;
160 	}
161 
162 	if (!soc->ops->l_flowctl_ops ||
163 	    !soc->ops->l_flowctl_ops->deregister_tx_flow_control_cb)
164 		return 0;
165 
166 	return soc->ops->l_flowctl_ops->deregister_tx_flow_control_cb(
167 			soc, vdev_id);
168 }
169 
170 /**
171  * cdp_fc_get_tx_resource() - get data path resource count
172  * @soc: data path soc handle
173  * @pdev_id: datapath pdev ID
174  * @peer_addr: peer mac address
175  * @low_watermark: low resource threshold
176  * @high_watermark_offset: high resource threshold
177  *
178  * get data path resource count
179  *
180  * Return: true enough data path resource available
181  *        false resource is not available
182  */
183 static inline bool
cdp_fc_get_tx_resource(ol_txrx_soc_handle soc,uint8_t pdev_id,struct qdf_mac_addr peer_addr,unsigned int low_watermark,unsigned int high_watermark_offset)184 cdp_fc_get_tx_resource(ol_txrx_soc_handle soc, uint8_t pdev_id,
185 		       struct qdf_mac_addr peer_addr,
186 		       unsigned int low_watermark,
187 		       unsigned int high_watermark_offset)
188 {
189 	if (!soc || !soc->ops) {
190 		dp_cdp_debug("invalid instance");
191 		QDF_BUG(0);
192 		return false;
193 	}
194 
195 	if (!soc->ops->l_flowctl_ops ||
196 	    !soc->ops->l_flowctl_ops->get_tx_resource)
197 		return false;
198 
199 	return soc->ops->l_flowctl_ops->get_tx_resource(soc, pdev_id, peer_addr,
200 							low_watermark,
201 							high_watermark_offset);
202 }
203 
204 /**
205  * cdp_fc_ll_set_tx_pause_q_depth() - set pause queue depth
206  * @soc: data path soc handle
207  * @vdev_id: virtual interface id to register flow control
208  * @pause_q_depth: pending tx queue delth
209  *
210  * set pause queue depth
211  *
212  * Return: 0 success
213  */
214 static inline int
cdp_fc_ll_set_tx_pause_q_depth(ol_txrx_soc_handle soc,uint8_t vdev_id,int pause_q_depth)215 cdp_fc_ll_set_tx_pause_q_depth(ol_txrx_soc_handle soc,
216 		uint8_t vdev_id, int pause_q_depth)
217 {
218 	if (!soc || !soc->ops) {
219 		dp_cdp_debug("invalid instance");
220 		QDF_BUG(0);
221 		return 0;
222 	}
223 
224 	if (!soc->ops->l_flowctl_ops ||
225 	    !soc->ops->l_flowctl_ops->ll_set_tx_pause_q_depth)
226 		return 0;
227 
228 	return soc->ops->l_flowctl_ops->ll_set_tx_pause_q_depth(
229 			soc, vdev_id, pause_q_depth);
230 
231 }
232 
233 /**
234  * cdp_fc_vdev_flush() - flush tx queue
235  * @soc: data path soc handle
236  * @vdev_id: id of vdev
237  *
238  * flush tx queue
239  *
240  * Return: None
241  */
242 static inline void
cdp_fc_vdev_flush(ol_txrx_soc_handle soc,uint8_t vdev_id)243 cdp_fc_vdev_flush(ol_txrx_soc_handle soc, uint8_t vdev_id)
244 {
245 	if (!soc || !soc->ops) {
246 		dp_cdp_debug("invalid instance");
247 		QDF_BUG(0);
248 		return;
249 	}
250 
251 	if (!soc->ops->l_flowctl_ops ||
252 	    !soc->ops->l_flowctl_ops->vdev_flush)
253 		return;
254 
255 	soc->ops->l_flowctl_ops->vdev_flush(soc, vdev_id);
256 }
257 
258 /**
259  * cdp_fc_vdev_pause() - pause tx scheduler on vdev
260  * @soc: data path soc handle
261  * @vdev_id: id of vdev
262  * @reason: pause reason
263  * @pause_type: type of pause
264  *
265  * pause tx scheduler on vdev
266  *
267  * Return: None
268  */
269 static inline void
cdp_fc_vdev_pause(ol_txrx_soc_handle soc,uint8_t vdev_id,uint32_t reason,uint32_t pause_type)270 cdp_fc_vdev_pause(ol_txrx_soc_handle soc, uint8_t vdev_id,
271 		  uint32_t reason, uint32_t pause_type)
272 {
273 	if (!soc || !soc->ops) {
274 		dp_cdp_debug("invalid instance");
275 		QDF_BUG(0);
276 		return;
277 	}
278 
279 	if (!soc->ops->l_flowctl_ops ||
280 	    !soc->ops->l_flowctl_ops->vdev_pause)
281 		return;
282 
283 	soc->ops->l_flowctl_ops->vdev_pause(soc, vdev_id, reason, pause_type);
284 }
285 
286 /**
287  * cdp_fc_vdev_unpause() - resume tx scheduler on vdev
288  * @soc: data path soc handle
289  * @vdev_id: id of vdev
290  * @reason: pause reason
291  * @pause_type: type of pause
292  *
293  * resume tx scheduler on vdev
294  *
295  * Return: None
296  */
297 static inline void
cdp_fc_vdev_unpause(ol_txrx_soc_handle soc,uint8_t vdev_id,uint32_t reason,uint32_t pause_type)298 cdp_fc_vdev_unpause(ol_txrx_soc_handle soc, uint8_t vdev_id,
299 		    uint32_t reason, uint32_t pause_type)
300 {
301 	if (!soc || !soc->ops) {
302 		dp_cdp_debug("invalid instance");
303 		return;
304 	}
305 
306 	if (!soc->ops->l_flowctl_ops ||
307 	    !soc->ops->l_flowctl_ops->vdev_unpause)
308 		return;
309 
310 	soc->ops->l_flowctl_ops->vdev_unpause(soc, vdev_id, reason,
311 					      pause_type);
312 }
313 #endif /* _CDP_TXRX_FC_LEG_H_ */
314