1 /* 2 * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 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 * @file ol_tx.h 22 * @brief Internal definitions for the high-level tx module. 23 */ 24 #ifndef _OL_TX__H_ 25 #define _OL_TX__H_ 26 27 #include <qdf_nbuf.h> /* qdf_nbuf_t */ 28 #include <qdf_lock.h> 29 #include <cdp_txrx_cmn.h> /* ol_txrx_vdev_t, etc. */ 30 #include <cdp_txrx_misc.h> /* ol_tx_spec */ 31 #include <cdp_txrx_handle.h> 32 #include <ol_txrx_types.h> /* ol_tx_desc_t, ol_txrx_msdu_info_t */ 33 #include <ol_txrx.h> 34 #include <hif.h> 35 36 #ifdef IPA_OFFLOAD 37 /** 38 * ol_tx_send_ipa_data_frame() - send IPA data frame 39 * @soc_hdl: datapath soc handle 40 * @vdev: virtual interface id 41 * @skb: skb 42 * 43 * Return: skb/ NULL is for success 44 */ 45 qdf_nbuf_t ol_tx_send_ipa_data_frame(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 46 qdf_nbuf_t skb); 47 #endif 48 49 #ifdef CONFIG_LL_DP_SUPPORT 50 struct ol_tx_desc_t * 51 ol_tx_prepare_ll(ol_txrx_vdev_handle vdev, 52 qdf_nbuf_t msdu, 53 struct ol_txrx_msdu_info_t *msdu_info); 54 #endif 55 56 qdf_nbuf_t ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); 57 #ifdef WLAN_FEATURE_FASTPATH 58 qdf_nbuf_t ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); 59 60 void ol_tx_setup_fastpath_ce_handles(struct hif_opaque_softc *osc, 61 struct ol_txrx_pdev_t *pdev); 62 #else 63 static inline ol_tx_setup_fastpath_ce_handles(struct hif_opaque_softc * osc,struct ol_txrx_pdev_t * pdev)64 void ol_tx_setup_fastpath_ce_handles(struct hif_opaque_softc *osc, 65 struct ol_txrx_pdev_t *pdev) 66 { } 67 68 qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); 69 #endif 70 71 qdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); 72 73 #ifdef CONFIG_HL_SUPPORT 74 #define OL_TX_SEND ol_tx_hl 75 #else 76 #define OL_TX_SEND OL_TX_LL 77 #endif 78 79 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL 80 #define OL_TX_LL ol_tx_ll_queue 81 #else 82 #define OL_TX_LL ol_tx_ll_wrapper 83 #endif 84 85 #ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE 86 void ol_tx_hl_vdev_bundle_timer(void *context); 87 88 void ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t *vdev); 89 qdf_nbuf_t 90 ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t *pdev); 91 #else 92 static inline ol_tx_hl_vdev_bundle_timer(void * context)93 void ol_tx_hl_vdev_bundle_timer(void *context) 94 { 95 } 96 97 static inline ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t * vdev)98 void ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t *vdev) 99 { 100 } 101 102 static inline 103 qdf_nbuf_t ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t * pdev)104 ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t *pdev) 105 { 106 return NULL; 107 } 108 #endif 109 110 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL 111 void ol_tx_vdev_ll_pause_queue_send(void *context); 112 void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev); 113 #else ol_tx_vdev_ll_pause_queue_send(void * context)114 static inline void ol_tx_vdev_ll_pause_queue_send(void *context) 115 { 116 } 117 static inline ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t * pdev)118 void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev) 119 { 120 } 121 #endif 122 123 /** 124 * ol_tx_comp_hw_to_qdf_status(): map ol hw to qdf status 125 * @status: hw status 126 * 127 * Return: qdf tx rx status 128 */ 129 static inline enum qdf_dp_tx_rx_status ol_tx_comp_hw_to_qdf_status(uint16_t status)130 ol_tx_comp_hw_to_qdf_status(uint16_t status) 131 { 132 switch (status) { 133 case HTT_TX_COMPL_IND_STAT_OK: 134 return QDF_TX_RX_STATUS_OK; 135 case HTT_TX_COMPL_IND_STAT_DISCARD: 136 case HTT_TX_COMPL_IND_STAT_DROP: 137 return QDF_TX_RX_STATUS_FW_DISCARD; 138 case HTT_TX_COMPL_IND_STAT_NO_ACK: 139 return QDF_TX_RX_STATUS_NO_ACK; 140 default: 141 return QDF_TX_RX_STATUS_DEFAULT; 142 } 143 } 144 145 static inline ol_txrx_tx_is_raw(enum ol_tx_spec tx_spec)146 int ol_txrx_tx_is_raw(enum ol_tx_spec tx_spec) 147 { 148 return tx_spec & 149 (OL_TX_SPEC_RAW | OL_TX_SPEC_NO_AGGR | OL_TX_SPEC_NO_ENCRYPT); 150 } 151 152 static inline ol_txrx_tx_raw_subtype(enum ol_tx_spec tx_spec)153 uint8_t ol_txrx_tx_raw_subtype(enum ol_tx_spec tx_spec) 154 { 155 uint8_t sub_type = 0x1; /* 802.11 MAC header present */ 156 157 if (tx_spec & OL_TX_SPEC_NO_AGGR) 158 sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_AGGR_S; 159 if (tx_spec & OL_TX_SPEC_NO_ENCRYPT) 160 sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S; 161 if (tx_spec & OL_TX_SPEC_NWIFI_NO_ENCRYPT) 162 sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S; 163 return sub_type; 164 } 165 166 /** 167 * ol_tx_hl() - transmit tx frames for a HL system. 168 * @vdev: the virtual device transmit the data 169 * @msdu_list: the tx frames to send 170 * 171 * Return: NULL if all MSDUs are accepted 172 */ 173 qdf_nbuf_t 174 ol_tx_hl(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list); 175 176 /** 177 * ol_tx_non_std() - Allow the control-path SW to send data frames 178 * @soc_hdl: Datapath soc handle 179 * @vdev_id: id of vdev 180 * @tx_spec: what non-standard handling to apply to the tx data frames 181 * @msdu_list: NULL-terminated list of tx MSDUs 182 * 183 * Generally, all tx data frames come from the OS shim into the txrx layer. 184 * However, there are rare cases such as TDLS messaging where the UMAC 185 * control-path SW creates tx data frames. 186 * This UMAC SW can call this function to provide the tx data frames to 187 * the txrx layer. 188 * The UMAC SW can request a callback for these data frames after their 189 * transmission completes, by using the ol_txrx_data_tx_cb_set function 190 * to register a tx completion callback, and by specifying 191 * ol_tx_spec_no_free as the tx_spec arg when giving the frames to 192 * ol_tx_non_std. 193 * The MSDUs need to have the appropriate L2 header type (802.3 vs. 802.11), 194 * as specified by ol_cfg_frame_type(). 195 * 196 * Return: null - success, skb - failure 197 */ 198 #ifdef CONFIG_HL_SUPPORT 199 qdf_nbuf_t ol_tx_non_std_hl(struct ol_txrx_vdev_t *vdev, 200 enum ol_tx_spec tx_spec, 201 qdf_nbuf_t msdu_list); 202 203 static inline qdf_nbuf_t ol_tx_non_std(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,enum ol_tx_spec tx_spec,qdf_nbuf_t msdu_list)204 ol_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 205 enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) 206 { 207 struct ol_txrx_vdev_t *vdev; 208 209 vdev = (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id); 210 211 if (!vdev) 212 return msdu_list; 213 else 214 return ol_tx_non_std_hl(vdev, tx_spec, msdu_list); 215 } 216 #else 217 qdf_nbuf_t ol_tx_non_std_ll(struct ol_txrx_vdev_t *vdev, 218 enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list); 219 220 static inline qdf_nbuf_t ol_tx_non_std(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,enum ol_tx_spec tx_spec,qdf_nbuf_t msdu_list)221 ol_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, 222 enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) 223 { 224 struct ol_txrx_vdev_t *vdev; 225 226 vdev = (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id); 227 228 if (!vdev) 229 return msdu_list; 230 else 231 return ol_tx_non_std_ll(vdev, tx_spec, msdu_list); 232 } 233 #endif 234 235 /** 236 * ol_tx_trace_pkt() - Trace TX packet at OL layer 237 * 238 * @skb: skb to be traced 239 * @msdu_id: msdu_id of the packet 240 * @vdev_id: vdev_id of the packet 241 * @op_mode: Vdev Operation mode 242 * 243 * Return: None 244 */ 245 void ol_tx_trace_pkt(qdf_nbuf_t skb, uint16_t msdu_id, uint8_t vdev_id, 246 enum QDF_OPMODE op_mode); 247 248 void ol_txrx_mgmt_tx_complete(void *ctxt, qdf_nbuf_t netbuf, int err); 249 250 /** 251 * ol_txrx_mgmt_tx_cb_set() - Store a callback for delivery 252 * notifications for management frames. 253 * @soc: Datapath soc handle 254 * @pdev_id: Physical device instance id 255 * @type: the type of mgmt frame the callback is used for 256 * @download_cb: the callback for notification of delivery to the target 257 * @ota_ack_cb: the callback for notification of delivery to the peer 258 * @ctxt: context to use with the callback 259 * 260 * When the txrx SW receives notifications from the target that a tx frame 261 * has been delivered to its recipient, it will check if the tx frame 262 * is a management frame. If so, the txrx SW will check the management 263 * frame type specified when the frame was submitted for transmission. 264 * If there is a callback function registered for the type of management 265 * frame in question, the txrx code will invoke the callback to inform 266 * the management + control SW that the mgmt frame was delivered. 267 * This function is used by the control SW to store a callback pointer 268 * for a given type of management frame. 269 */ 270 QDF_STATUS 271 ol_txrx_mgmt_tx_cb_set(struct cdp_soc_t *soc, uint8_t pdev_id, uint8_t type, 272 ol_txrx_mgmt_tx_cb download_cb, 273 ol_txrx_mgmt_tx_cb ota_ack_cb, void *ctxt); 274 275 /** 276 * ol_txrx_mgmt_send_ext() - Transmit a management frame 277 * @soc: Datapath soc handle 278 * @vdev_id: virtual interface id 279 * @tx_mgmt_frm: management frame to transmit 280 * @type: the type of management frame (determines what callback to use) 281 * @use_6mbps: specify whether management frame to transmit should 282 * use 6 Mbps rather than 1 Mbps min rate(for 5GHz band or P2P) 283 * @chanfreq: channel to transmit the frame on 284 * 285 * Send the specified management frame from the specified virtual device. 286 * The type is used for determining whether to invoke a callback to inform 287 * the sender that the tx mgmt frame was delivered, and if so, which 288 * callback to use. 289 * 290 * Return: 0 - the frame is accepted for transmission 291 * 1 - the frame was not accepted 292 */ 293 int 294 ol_txrx_mgmt_send_ext(struct cdp_soc_t *soc, uint8_t vdev_id, 295 qdf_nbuf_t tx_mgmt_frm, 296 uint8_t type, uint8_t use_6mbps, uint16_t chanfreq); 297 298 qdf_nbuf_t 299 ol_tx_reinject(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu, uint16_t peer_id); 300 301 #if defined(FEATURE_TSO) 302 void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg); 303 void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev); 304 void ol_tso_num_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg); 305 void ol_tso_num_seg_list_deinit(struct ol_txrx_pdev_t *pdev); 306 uint32_t ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t *pdev); 307 uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev, 308 qdf_nbuf_t msdu, 309 struct ol_txrx_msdu_info_t *msdu_info); 310 void ol_tx_tso_update_stats(struct ol_txrx_pdev_t *pdev, 311 struct qdf_tso_info_t *tso_info, qdf_nbuf_t msdu, 312 uint32_t tso_msdu_idx); 313 #else ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t * pdev)314 static inline uint32_t ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t *pdev) 315 { 316 return 0; 317 } 318 ol_tso_seg_list_init(struct ol_txrx_pdev_t * pdev,uint32_t num_seg)319 static inline void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, 320 uint32_t num_seg) 321 { 322 } 323 ol_tso_seg_list_deinit(struct ol_txrx_pdev_t * pdev)324 static inline void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev) 325 { 326 } 327 ol_tso_num_seg_list_init(struct ol_txrx_pdev_t * pdev,uint32_t num_seg)328 static inline void ol_tso_num_seg_list_init(struct ol_txrx_pdev_t *pdev, 329 uint32_t num_seg) 330 { 331 } 332 ol_tso_num_seg_list_deinit(struct ol_txrx_pdev_t * pdev)333 static inline void ol_tso_num_seg_list_deinit(struct ol_txrx_pdev_t *pdev) 334 { 335 } 336 ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * msdu_info)337 static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev, 338 qdf_nbuf_t msdu, 339 struct ol_txrx_msdu_info_t *msdu_info) 340 { 341 return 0; 342 } 343 ol_tx_tso_update_stats(struct ol_txrx_pdev_t * pdev,struct qdf_tso_info_t * tso_info,qdf_nbuf_t msdu,uint32_t tso_msdu_idx)344 static inline void ol_tx_tso_update_stats(struct ol_txrx_pdev_t *pdev, 345 struct qdf_tso_info_t *tso_info, 346 qdf_nbuf_t msdu, 347 uint32_t tso_msdu_idx) 348 { 349 } 350 #endif 351 352 #ifdef QCA_HL_NETDEV_FLOW_CONTROL 353 bool ol_tx_desc_is_high_prio(qdf_nbuf_t msdu); 354 #endif 355 356 #if defined(HELIUMPLUS) 357 void ol_txrx_dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc); 358 #else 359 static inline ol_txrx_dump_frag_desc(char * msg,struct ol_tx_desc_t * tx_desc)360 void ol_txrx_dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc) 361 { 362 } 363 #endif 364 365 #endif /* _OL_TX__H_ */ 366