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