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