Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 1 | /* |
Dhanashri Atre | 83d373d | 2015-07-28 16:45:59 -0700 | [diff] [blame] | 2 | * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 3 | * |
| 4 | * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| 5 | * |
| 6 | * |
| 7 | * Permission to use, copy, modify, and/or distribute this software for |
| 8 | * any purpose with or without fee is hereby granted, provided that the |
| 9 | * above copyright notice and this permission notice appear in all |
| 10 | * copies. |
| 11 | * |
| 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| 13 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| 15 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| 16 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| 17 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 19 | * PERFORMANCE OF THIS SOFTWARE. |
| 20 | */ |
| 21 | |
| 22 | /* |
| 23 | * This file was originally distributed by Qualcomm Atheros, Inc. |
| 24 | * under proprietary terms before Copyright ownership was assigned |
| 25 | * to the Linux Foundation. |
| 26 | */ |
| 27 | |
| 28 | /** |
| 29 | * @file ol_htt_tx_api.h |
| 30 | * @brief Specify the tx HTT API functions called by the host data SW. |
| 31 | * @details |
| 32 | * This file declares the HTT API functions that are specifically |
| 33 | * related to transmit processing. |
| 34 | * In particular, the methods of the abstract HTT tx descriptor are |
| 35 | * specified. |
| 36 | */ |
| 37 | #ifndef _OL_HTT_TX_API__H_ |
| 38 | #define _OL_HTT_TX_API__H_ |
| 39 | |
| 40 | /* #include <osapi_linux.h> / * uint16_t, etc. * / */ |
| 41 | #include <osdep.h> /* uint16_t, etc. */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 42 | #include <qdf_nbuf.h> /* qdf_nbuf_t */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 43 | #include <ol_cfg.h> /* wlan_frm_fmt */ |
| 44 | |
| 45 | #include <htt.h> /* needed by inline functions */ |
Anurag Chouhan | c73697b | 2016-02-21 15:05:43 +0530 | [diff] [blame] | 46 | #include <qdf_net_types.h> |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 47 | #include <ol_htt_api.h> /* htt_pdev_handle */ |
| 48 | #include <htt_types.h> |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 49 | #include <qdf_trace.h> |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 50 | |
| 51 | /* Remove these macros when they get added to htt.h. */ |
| 52 | #ifndef HTT_TX_DESC_EXTENSION_GET |
| 53 | #define HTT_TX_DESC_EXTENSION_OFFSET_BYTES 0 |
| 54 | #define HTT_TX_DESC_EXTENSION_OFFSET_DWORD 0 |
| 55 | #define HTT_TX_DESC_EXTENSION_M 0x10000000 |
| 56 | #define HTT_TX_DESC_EXTENSION_S 28 |
| 57 | |
| 58 | #define HTT_TX_DESC_EXTENSION_GET(_var) \ |
| 59 | (((_var) & HTT_TX_DESC_EXTENSION_M) >> HTT_TX_DESC_EXTENSION_S) |
| 60 | #define HTT_TX_DESC_EXTENSION_SET(_var, _val) \ |
| 61 | do { \ |
| 62 | HTT_CHECK_SET_VAL(HTT_TX_DESC_EXTENSION, _val); \ |
| 63 | ((_var) |= ((_val) << HTT_TX_DESC_EXTENSION_S)); \ |
| 64 | } while (0) |
| 65 | #endif |
| 66 | |
| 67 | /*================ meta-info about tx MSDUs =================================*/ |
| 68 | |
| 69 | /* |
| 70 | * For simplicity, use the IEEE 802.11 frame type values. |
| 71 | */ |
| 72 | enum htt_frm_type { |
| 73 | htt_frm_type_mgmt = 0, |
| 74 | htt_frm_type_ctrl = 1, |
| 75 | htt_frm_type_data = 2 |
| 76 | }; |
| 77 | |
| 78 | /* |
| 79 | * For simplicity, use the IEEE 802.11 frame sub-type values. |
| 80 | */ |
| 81 | enum htt_frm_subtype { |
| 82 | htt_frm_subtype_mgmt_assoc_req = 0, |
| 83 | htt_frm_subtype_mgmt_assoc_resp = 1, |
| 84 | htt_frm_subtype_mgmt_reassoc_req = 2, |
| 85 | htt_frm_subtype_mgmt_reassoc_resp = 3, |
| 86 | htt_frm_subtype_mgmt_probe_req = 4, |
| 87 | htt_frm_subtype_mgmt_probe_resp = 5, |
| 88 | htt_frm_subtype_mgmt_timing_adv = 6, |
| 89 | htt_frm_subtype_mgmt_beacon = 8, |
| 90 | htt_frm_subtype_mgmt_atim = 9, |
| 91 | htt_frm_subtype_mgmt_disassoc = 10, |
| 92 | htt_frm_subtype_mgmt_auth = 11, |
| 93 | htt_frm_subtype_mgmt_deauth = 12, |
| 94 | htt_frm_subtype_mgmt_action = 13, |
| 95 | htt_frm_subtype_mgmt_action_no_ack = 14, |
| 96 | |
| 97 | htt_frm_subtype_data_data = 0, |
| 98 | htt_frm_subtype_data_data_cf_ack = 1, |
| 99 | htt_frm_subtype_data_data_cf_poll = 2, |
| 100 | htt_frm_subtype_data_data_cf_ack_cf_poll = 3, |
| 101 | htt_frm_subtype_data_null = 4, |
| 102 | htt_frm_subtype_data_cf_ack = 5, |
| 103 | htt_frm_subtype_data_cf_poll = 6, |
| 104 | htt_frm_subtype_data_cf_ack_cf_poll = 7, |
| 105 | htt_frm_subtype_data_QoS_data = 8, |
| 106 | htt_frm_subtype_data_QoS_data_cf_ack = 9, |
| 107 | htt_frm_subtype_data_QoS_data_cf_poll = 10, |
| 108 | htt_frm_subtype_data_QoS_data_cf_ack_cf_poll = 11, |
| 109 | htt_frm_subtype_data_QoS_null = 12, |
| 110 | htt_frm_subtype_data_QoS_cf_poll = 14, |
| 111 | htt_frm_subtype_data_QoS_cf_ack_cf_poll = 15, |
| 112 | }; |
| 113 | |
| 114 | enum htt_ofdm_datarate { /* Value MBPS Modulation Coding*/ |
| 115 | htt_ofdm_datarate_6_mbps = 0, /* 0 6 BPSK 1/2 */ |
| 116 | htt_ofdm_datarate_9_mbps = 1, /* 1 9 BPSK 3/4 */ |
| 117 | htt_ofdm_datarate_12_mbps = 2, /* 2 12 QPSK 1/2 */ |
| 118 | htt_ofdm_datarate_18_mbps = 3, /* 3 18 QPSK 3/4 */ |
| 119 | htt_ofdm_datarate_24_mbps = 4, /* 4 24 16-QAM 1/2 */ |
| 120 | htt_ofdm_datarate_36_mbps = 5, /* 5 36 16-QAM 3/4 */ |
| 121 | htt_ofdm_datarate_48_mbps = 6, /* 6 48 64-QAM 1/2 */ |
| 122 | htt_ofdm_datarate_54_mbps = 7, /* 7 54 64-QAM 3/4 */ |
| 123 | htt_ofdm_datarate_max = 7, |
| 124 | }; |
| 125 | |
| 126 | /** |
| 127 | * struct ocb_tx_ctrl_hdr_t - TX control header |
| 128 | * @version: must be 1 |
| 129 | * @length: length of this structure |
| 130 | * @channel_freq: channel on which to transmit the packet |
| 131 | * @valid_pwr: bit 0: if set, tx pwr spec is valid |
| 132 | * @valid_datarate: bit 1: if set, tx MCS mask spec is valid |
| 133 | * @valid_retries: bit 2: if set, tx retries spec is valid |
| 134 | * @valid_chain_mask: bit 3: if set, chain mask is valid |
| 135 | * @valid_expire_tsf: bit 4: if set, tx expire TSF spec is valid |
| 136 | * @valid_tid: bit 5: if set, TID is valid |
| 137 | * @reserved0_15_6: bits 15:6 - unused, set to 0x0 |
| 138 | * @all_flags: union of all the flags |
| 139 | * @expire_tsf_lo: TX expiry time (TSF) LSBs |
| 140 | * @expire_tsf_hi: TX expiry time (TSF) MSBs |
| 141 | * @pwr: Specify what power the tx frame needs to be transmitted |
| 142 | * at. The power a signed (two's complement) value is in |
| 143 | * units of 0.5 dBm. The value needs to be appropriately |
| 144 | * sign-extended when extracting the value from the message |
| 145 | * and storing it in a variable that is larger than A_INT8. |
| 146 | * If the transmission uses multiple tx chains, this power |
| 147 | * spec is the total transmit power, assuming incoherent |
| 148 | * combination of per-chain power to produce the total |
| 149 | * power. |
| 150 | * @datarate: The desired modulation and coding scheme. |
| 151 | * VALUE DATA RATE MODULATION CODING RATE |
| 152 | * @ 20 MHz |
| 153 | * (MBPS) |
| 154 | * 0 6 BPSK 1/2 |
| 155 | * 1 9 BPSK 3/4 |
| 156 | * 2 12 QPSK 1/2 |
| 157 | * 3 18 QPSK 3/4 |
| 158 | * 4 24 16-QAM 1/2 |
| 159 | * 5 36 16-QAM 3/4 |
| 160 | * 6 48 64-QAM 1/2 |
| 161 | * 7 54 64-QAM 3/4 |
| 162 | * @retry_limit: Specify the maximum number of transmissions, including |
| 163 | * the initial transmission, to attempt before giving up if |
| 164 | * no ack is received. |
| 165 | * If the tx rate is specified, then all retries shall use |
| 166 | * the same rate as the initial transmission. |
| 167 | * If no tx rate is specified, the target can choose |
| 168 | * whether to retain the original rate during the |
| 169 | * retransmissions, or to fall back to a more robust rate. |
| 170 | * @chain_mask: specify which chains to transmit from |
| 171 | * @ext_tid: Extended Traffic ID (0-15) |
| 172 | * @reserved: Ensure that the size of the structure is a multiple of |
| 173 | * 4. Must be 0. |
| 174 | * |
| 175 | * When sending an OCB packet, the user application has |
| 176 | * the option of including the following struct following an ethernet header |
| 177 | * with the proto field set to 0x8151. This struct includes various TX |
| 178 | * paramaters including the TX power and MCS. |
| 179 | */ |
| 180 | PREPACK struct ocb_tx_ctrl_hdr_t { |
| 181 | uint16_t version; |
| 182 | uint16_t length; |
| 183 | uint16_t channel_freq; |
| 184 | |
| 185 | union { |
| 186 | struct { |
| 187 | uint16_t |
| 188 | valid_pwr:1, |
| 189 | valid_datarate:1, |
| 190 | valid_retries:1, |
| 191 | valid_chain_mask:1, |
| 192 | valid_expire_tsf:1, |
| 193 | valid_tid:1, |
| 194 | reserved0_15_6:10; |
| 195 | }; |
| 196 | uint16_t all_flags; |
| 197 | }; |
| 198 | |
| 199 | uint32_t expire_tsf_lo; |
| 200 | uint32_t expire_tsf_hi; |
| 201 | int8_t pwr; |
| 202 | uint8_t datarate; |
| 203 | uint8_t retry_limit; |
| 204 | uint8_t chain_mask; |
| 205 | uint8_t ext_tid; |
| 206 | uint8_t reserved[3]; |
| 207 | } POSTPACK; |
| 208 | |
| 209 | /** |
| 210 | * @brief tx MSDU meta-data that HTT may use to program the FW/HW tx descriptor |
| 211 | */ |
| 212 | struct htt_msdu_info_t { |
| 213 | /* the info sub-struct specifies the characteristics of the MSDU */ |
| 214 | struct { |
| 215 | uint16_t ethertype; |
| 216 | #define HTT_INVALID_PEER_ID 0xffff |
| 217 | uint16_t peer_id; |
| 218 | uint8_t vdev_id; |
| 219 | uint8_t ext_tid; |
| 220 | /* |
| 221 | * l2_hdr_type - L2 format (802.3, native WiFi 802.11, |
| 222 | * or raw 802.11) |
| 223 | * Based on attach-time configuration, the tx frames provided |
| 224 | * by the OS to the tx data SW are expected to be either |
| 225 | * 802.3 format or the "native WiFi" variant of 802.11 format. |
| 226 | * Internally, the driver may also inject tx frames into the tx |
| 227 | * datapath, and these frames may be either 802.3 format or |
| 228 | * 802.11 "raw" format, with no further 802.11 encapsulation |
| 229 | * needed. |
| 230 | * The tx frames are tagged with their frame format, so target |
| 231 | * FW/HW will know how to interpret the packet's encapsulation |
| 232 | * headers when doing tx classification, and what form of 802.11 |
| 233 | * header encapsulation is needed, if any. |
| 234 | */ |
| 235 | uint8_t l2_hdr_type; /* enum htt_pkt_type */ |
| 236 | /* |
| 237 | * frame_type - is the tx frame management or data? |
| 238 | * Just to avoid confusion, the enum values for this frame type |
| 239 | * field use the 802.11 frame type values, although it is |
| 240 | * unexpected for control frames to be sent through the host |
| 241 | * data path. |
| 242 | */ |
| 243 | uint8_t frame_type; /* enum htt_frm_type */ |
| 244 | /* |
| 245 | * frame subtype - this field specifies the sub-type of |
| 246 | * management frames |
| 247 | * Just to avoid confusion, the enum values for this frame |
| 248 | * subtype field use the 802.11 management frame subtype values. |
| 249 | */ |
| 250 | uint8_t frame_subtype; /* enum htt_frm_subtype */ |
| 251 | uint8_t is_unicast; |
| 252 | |
| 253 | /* dest_addr is not currently used. |
| 254 | * It could be used as an input to a Tx BD (Riva tx descriptor) |
| 255 | * signature computation. |
| 256 | uint8_t *dest_addr; |
| 257 | */ |
| 258 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 259 | uint8_t l3_hdr_offset; /* wrt qdf_nbuf_data(msdu), in bytes */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 260 | |
| 261 | /* l4_hdr_offset is not currently used. |
| 262 | * It could be used to specify to a TCP/UDP checksum computation |
| 263 | * engine where the TCP/UDP header starts. |
| 264 | */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 265 | /* uint8_t l4_hdr_offset; - wrt qdf_nbuf_data(msdu), in bytes */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 266 | } info; |
| 267 | /* the action sub-struct specifies how to process the MSDU */ |
| 268 | struct { |
| 269 | uint8_t use_6mbps; /* mgmt frames: option to force |
| 270 | 6 Mbps rate */ |
| 271 | uint8_t do_encrypt; |
| 272 | uint8_t do_tx_complete; |
| 273 | uint8_t tx_comp_req; |
| 274 | |
| 275 | /* |
| 276 | * cksum_offload - Specify whether checksum offload is |
| 277 | * enabled or not |
| 278 | * Target FW uses this flag to turn on HW checksumming |
| 279 | * 0x0 - No checksum offload |
| 280 | * 0x1 - L3 header checksum only |
| 281 | * 0x2 - L4 checksum only |
| 282 | * 0x3 - L3 header checksum + L4 checksum |
| 283 | */ |
Anurag Chouhan | c73697b | 2016-02-21 15:05:43 +0530 | [diff] [blame] | 284 | qdf_nbuf_tx_cksum_t cksum_offload; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 285 | } action; |
| 286 | }; |
| 287 | |
| 288 | static inline void htt_msdu_info_dump(struct htt_msdu_info_t *msdu_info) |
| 289 | { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 290 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 291 | "HTT MSDU info object (%p)\n", msdu_info); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 292 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 293 | " ethertype: %#x\n", msdu_info->info.ethertype); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 294 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 295 | " peer_id: %d\n", msdu_info->info.peer_id); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 296 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 297 | " vdev_id: %d\n", msdu_info->info.vdev_id); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 298 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 299 | " ext_tid: %d\n", msdu_info->info.ext_tid); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 300 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 301 | " l2_hdr_type: %d\n", msdu_info->info.l2_hdr_type); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 302 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 303 | " frame_type: %d\n", msdu_info->info.frame_type); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 304 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 305 | " frame_subtype: %d\n", msdu_info->info.frame_subtype); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 306 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 307 | " is_unicast: %u\n", msdu_info->info.is_unicast); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 308 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 309 | " l3_hdr_offset: %u\n", msdu_info->info.l3_hdr_offset); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 310 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 311 | " use 6 Mbps: %d\n", msdu_info->action.use_6mbps); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 312 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 313 | " do_encrypt: %d\n", msdu_info->action.do_encrypt); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 314 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 315 | " do_tx_complete: %d\n", msdu_info->action.do_tx_complete); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 316 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 317 | " is_unicast: %u\n", msdu_info->info.is_unicast); |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 318 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 319 | " is_unicast: %u\n", msdu_info->info.is_unicast); |
| 320 | } |
| 321 | |
| 322 | /*================ tx completion message field access methods ===============*/ |
| 323 | |
| 324 | /** |
| 325 | * @brief Look up the descriptor ID of the nth MSDU from a tx completion msg. |
| 326 | * @details |
| 327 | * A tx completion message tells the host that the target is done |
| 328 | * transmitting a series of MSDUs. The message uses a descriptor ID |
| 329 | * to identify each such MSDU. This function/macro is used to |
| 330 | * find the ID of one such MSDU referenced by the tx completion message. |
| 331 | * |
| 332 | * @param iterator - tx completion message context provided by HTT to the |
| 333 | * tx completion message handler. This abstract reference to the |
| 334 | * HTT tx completion message's payload allows the data SW's tx |
| 335 | * completion handler to not care about the format of the HTT |
| 336 | * tx completion message. |
| 337 | * @param num - (zero-based) index to specify a single MSDU within the |
| 338 | * series of MSDUs referenced by the tx completion message |
| 339 | * @return descriptor ID for the specified MSDU |
| 340 | */ |
| 341 | uint16_t htt_tx_compl_desc_id(void *iterator, int num); |
| 342 | |
| 343 | /*========================= tx descriptor operations ========================*/ |
| 344 | |
| 345 | /** |
| 346 | * @brief Allocate a HTT abstract tx descriptor. |
| 347 | * @details |
| 348 | * Allocate a HTT abstract tx descriptor from a pool within "consistent" |
| 349 | * memory, which is accessible by HIF and/or MAC DMA as well as by the |
| 350 | * host CPU. |
| 351 | * It is expected that the tx datapath will allocate HTT tx descriptors |
| 352 | * and link them with datapath SW tx descriptors up front as the driver |
| 353 | * is loaded. Thereafter, the link from datapath SW tx descriptor to |
| 354 | * HTT tx descriptor will be maintained until the driver is unloaded. |
| 355 | * |
| 356 | * @param htt_pdev - handle to the HTT instance making the allocation |
| 357 | * @param[OUT] paddr_lo - physical address of the HTT descriptor |
| 358 | * @return success -> descriptor handle, -OR- failure -> NULL |
| 359 | */ |
Anurag Chouhan | df2b268 | 2016-02-29 14:15:27 +0530 | [diff] [blame] | 360 | void *htt_tx_desc_alloc(htt_pdev_handle pdev, qdf_dma_addr_t *paddr, |
Leo Chang | 376398b | 2015-10-23 14:19:02 -0700 | [diff] [blame] | 361 | uint16_t index); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 362 | |
| 363 | /** |
| 364 | * @brief Free a HTT abstract tx descriptor. |
| 365 | * |
| 366 | * @param htt_pdev - handle to the HTT instance that made the allocation |
| 367 | * @param htt_tx_desc - the descriptor to free |
| 368 | */ |
| 369 | void htt_tx_desc_free(htt_pdev_handle htt_pdev, void *htt_tx_desc); |
| 370 | |
| 371 | #if defined(HELIUMPLUS_PADDR64) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 372 | /** |
Leo Chang | 376398b | 2015-10-23 14:19:02 -0700 | [diff] [blame] | 373 | * @brief Allocate TX frag descriptor |
| 374 | * @details |
| 375 | * Allocate TX frag descriptor |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 376 | * |
Leo Chang | 376398b | 2015-10-23 14:19:02 -0700 | [diff] [blame] | 377 | * @param pdev - handle to the HTT instance that made the allocation |
| 378 | * @param index - tx descriptor index |
| 379 | * @param frag_paddr_lo - fragment descriptor physical address lower 32bits |
| 380 | * @param frag_ptr - fragment descriptor hlos pointe |
| 381 | * @return success 0 |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 382 | */ |
Leo Chang | 376398b | 2015-10-23 14:19:02 -0700 | [diff] [blame] | 383 | int htt_tx_frag_alloc(htt_pdev_handle pdev, |
Anurag Chouhan | df2b268 | 2016-02-29 14:15:27 +0530 | [diff] [blame] | 384 | u_int16_t index, qdf_dma_addr_t *frag_paddr, void **frag_ptr); |
Leo Chang | 376398b | 2015-10-23 14:19:02 -0700 | [diff] [blame] | 385 | #else |
| 386 | static inline int htt_tx_frag_alloc(htt_pdev_handle pdev, |
Anurag Chouhan | df2b268 | 2016-02-29 14:15:27 +0530 | [diff] [blame] | 387 | u_int16_t index, qdf_dma_addr_t *frag_paddr, void **frag_ptr) |
Leo Chang | 376398b | 2015-10-23 14:19:02 -0700 | [diff] [blame] | 388 | { |
| 389 | *frag_ptr = NULL; |
| 390 | return 0; |
| 391 | } |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 392 | #endif /* defined(HELIUMPLUS_PADDR64) */ |
| 393 | /** |
| 394 | * @brief Discard all tx frames in the process of being downloaded. |
| 395 | * @details |
| 396 | * This function dicards any tx frames queued in HTT or the layers |
| 397 | * under HTT. |
| 398 | * The download completion callback is invoked on these frames. |
| 399 | * |
| 400 | * @param htt_pdev - handle to the HTT instance |
| 401 | * @param[OUT] frag_paddr_lo - physical address of the fragment descriptor |
| 402 | * (MSDU Link Extension Descriptor) |
| 403 | */ |
| 404 | void htt_tx_pending_discard(htt_pdev_handle pdev); |
| 405 | |
| 406 | /** |
| 407 | * @brief Download a MSDU descriptor and (a portion of) the MSDU payload. |
| 408 | * @details |
| 409 | * This function is used within LL systems to download a tx descriptor and |
| 410 | * the initial portion of the tx MSDU payload, and within HL systems to |
| 411 | * download the tx descriptor and the entire tx MSDU payload. |
| 412 | * The HTT layer determines internally how much of the tx descriptor |
| 413 | * actually needs to be downloaded. In particular, the HTT layer does not |
| 414 | * download the fragmentation descriptor, and only for the LL case downloads |
| 415 | * the physical address of the fragmentation descriptor. |
| 416 | * In HL systems, the tx descriptor and the entire frame are downloaded. |
| 417 | * In LL systems, only the tx descriptor and the header of the frame are |
| 418 | * downloaded. To determine how much of the tx frame to download, this |
| 419 | * function assumes the tx frame is the default frame type, as specified |
| 420 | * by ol_cfg_frame_type. "Raw" frames need to be transmitted through the |
| 421 | * alternate htt_tx_send_nonstd function. |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 422 | * The tx descriptor has already been attached to the qdf_nbuf object during |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 423 | * a preceding call to htt_tx_desc_init. |
| 424 | * |
| 425 | * @param htt_pdev - the handle of the physical device sending the tx data |
| 426 | * @param msdu - the frame being transmitted |
| 427 | * @param msdu_id - unique ID for the frame being transmitted |
| 428 | * @return 0 -> success, -OR- 1 -> failure |
| 429 | */ |
| 430 | int |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 431 | htt_tx_send_std(htt_pdev_handle htt_pdev, qdf_nbuf_t msdu, uint16_t msdu_id); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 432 | |
| 433 | /** |
| 434 | * @brief Download a Batch Of Tx MSDUs |
| 435 | * @details |
| 436 | * Each MSDU already has the MSDU ID stored in the headroom of the |
| 437 | * netbuf data buffer, and has the HTT tx descriptor already attached |
| 438 | * as a prefix fragment to the netbuf. |
| 439 | * |
| 440 | * @param htt_pdev - the handle of the physical device sending the tx data |
| 441 | * @param head_msdu - the MSDU Head for Tx batch being transmitted |
| 442 | * @param num_msdus - The total Number of MSDU's provided for batch tx |
| 443 | * @return null-terminated linked-list of unaccepted frames |
| 444 | */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 445 | qdf_nbuf_t |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 446 | htt_tx_send_batch(htt_pdev_handle htt_pdev, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 447 | qdf_nbuf_t head_msdu, int num_msdus); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 448 | |
| 449 | /* The htt scheduler for queued packets in htt |
| 450 | * htt when unable to send to HTC because of lack of resource |
| 451 | * forms a nbuf queue which is flushed when tx completion event from |
| 452 | * target is recieved |
| 453 | */ |
| 454 | |
| 455 | void htt_tx_sched(htt_pdev_handle pdev); |
| 456 | |
| 457 | /** |
| 458 | * @brief Same as htt_tx_send_std, but can handle raw frames. |
| 459 | */ |
| 460 | int |
| 461 | htt_tx_send_nonstd(htt_pdev_handle htt_pdev, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 462 | qdf_nbuf_t msdu, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 463 | uint16_t msdu_id, enum htt_pkt_type pkt_type); |
| 464 | |
| 465 | /** |
| 466 | * htt_pkt_dl_len_get() Gets the HTT PKT download length. |
| 467 | * @pdev: pointer to struct htt_pdev_t |
| 468 | * |
| 469 | * Return: size of HTT packet download length. |
| 470 | */ |
| 471 | int |
| 472 | htt_pkt_dl_len_get(struct htt_pdev_t *pdev); |
| 473 | |
| 474 | #define HTT_TX_CLASSIFY_BIT_S 4 /* Used to set |
| 475 | * classify bit in HTT desc.*/ |
| 476 | |
| 477 | /** |
| 478 | * enum htt_ce_tx_pkt_type - enum of packet types to be set in CE |
| 479 | * descriptor |
| 480 | * @tx_pkt_type_raw: Value set for RAW frames |
| 481 | * @tx_pkt_type_native_wifi: Value set for NATIVE WIFI frames |
| 482 | * @tx_pkt_type_eth2: Value set for Ethernet II frames (mostly default) |
| 483 | * @tx_pkt_type_802_3: Value set for 802.3 / original ethernet frames |
| 484 | * @tx_pkt_type_mgmt: Value set for MGMT frames over HTT |
| 485 | * |
| 486 | */ |
| 487 | enum htt_ce_tx_pkt_type { |
| 488 | tx_pkt_type_raw = 0, |
| 489 | tx_pkt_type_native_wifi = 1, |
| 490 | tx_pkt_type_eth2 = 2, |
| 491 | tx_pkt_type_802_3 = 3, |
| 492 | tx_pkt_type_mgmt = 4 |
| 493 | }; |
| 494 | |
| 495 | |
| 496 | extern const uint32_t htt_to_ce_pkt_type[]; |
| 497 | |
| 498 | /** |
| 499 | * Provide a constant to specify the offset of the HTT portion of the |
| 500 | * HTT tx descriptor, to avoid having to export the descriptor defintion. |
| 501 | * The htt module checks internally that this exported offset is consistent |
| 502 | * with the private tx descriptor definition. |
| 503 | * |
| 504 | * Similarly, export a definition of the HTT tx descriptor size, and then |
| 505 | * check internally that this exported constant matches the private tx |
| 506 | * descriptor definition. |
| 507 | */ |
| 508 | #define HTT_TX_DESC_VADDR_OFFSET 8 |
| 509 | |
| 510 | /** |
| 511 | * htt_tx_desc_init() - Initialize the per packet HTT Tx descriptor |
| 512 | * @pdev: The handle of the physical device sending the |
| 513 | * tx data |
| 514 | * @htt_tx_desc: Abstract handle to the tx descriptor |
| 515 | * @htt_tx_desc_paddr_lo: Physical address of the HTT tx descriptor |
| 516 | * @msdu_id: ID to tag the descriptor with. |
| 517 | * The FW sends this ID back to host as a cookie |
| 518 | * during Tx completion, which the host uses to |
| 519 | * identify the MSDU. |
| 520 | * This ID is an index into the OL Tx desc. array. |
| 521 | * @msdu: The MSDU that is being prepared for transmission |
| 522 | * @msdu_info: Tx MSDU meta-data |
| 523 | * @tso_info: Storage for TSO meta-data |
| 524 | * |
| 525 | * This function initializes the HTT tx descriptor. |
| 526 | * HTT Tx descriptor is a host-f/w interface structure, and meta-data |
| 527 | * accompanying every packet downloaded to f/w via the HTT interface. |
| 528 | */ |
| 529 | static inline |
| 530 | void |
| 531 | htt_tx_desc_init(htt_pdev_handle pdev, |
| 532 | void *htt_tx_desc, |
Anurag Chouhan | df2b268 | 2016-02-29 14:15:27 +0530 | [diff] [blame] | 533 | qdf_dma_addr_t htt_tx_desc_paddr, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 534 | uint16_t msdu_id, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 535 | qdf_nbuf_t msdu, struct htt_msdu_info_t *msdu_info, |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 536 | struct qdf_tso_info_t *tso_info, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 537 | struct ocb_tx_ctrl_hdr_t *tx_ctrl, |
| 538 | uint8_t is_dsrc) |
| 539 | { |
| 540 | uint8_t pkt_type, pkt_subtype = 0, ce_pkt_type = 0; |
| 541 | uint32_t hw_classify = 0, data_attr = 0; |
| 542 | uint32_t *word0, *word1, local_word3; |
| 543 | #if HTT_PADDR64 |
| 544 | uint32_t *word4; |
| 545 | #else /* ! HTT_PADDR64 */ |
| 546 | uint32_t *word3; |
| 547 | #endif /* HTT_PADDR64 */ |
| 548 | uint32_t local_word0, local_word1; |
| 549 | struct htt_host_tx_desc_t *htt_host_tx_desc = |
| 550 | (struct htt_host_tx_desc_t *) |
| 551 | (((char *)htt_tx_desc) - HTT_TX_DESC_VADDR_OFFSET); |
| 552 | bool desc_ext_required = (tx_ctrl && tx_ctrl->all_flags != 0); |
| 553 | |
| 554 | word0 = (uint32_t *) htt_tx_desc; |
| 555 | word1 = word0 + 1; |
| 556 | /* |
| 557 | * word2 is frag desc pointer |
| 558 | * word3 or 4 is peer_id |
| 559 | */ |
| 560 | #if HTT_PADDR64 |
| 561 | word4 = word0 + 4; /* Dword 3 */ |
| 562 | #else /* ! HTT_PADDR64 */ |
| 563 | word3 = word0 + 3; /* Dword 3 */ |
| 564 | #endif /* HTT_PADDR64 */ |
| 565 | |
| 566 | pkt_type = msdu_info->info.l2_hdr_type; |
| 567 | |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 568 | if (qdf_likely(pdev->cfg.ce_classify_enabled)) { |
| 569 | if (qdf_likely(pkt_type == htt_pkt_type_eth2 || |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 570 | pkt_type == htt_pkt_type_ethernet)) |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 571 | qdf_nbuf_tx_info_get(msdu, pkt_type, pkt_subtype, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 572 | hw_classify); |
| 573 | |
| 574 | ce_pkt_type = htt_to_ce_pkt_type[pkt_type]; |
| 575 | if (0xffffffff == ce_pkt_type) { |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 576 | QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 577 | "Invalid HTT pkt type %d\n", pkt_type); |
| 578 | return; |
| 579 | } |
| 580 | } |
| 581 | |
| 582 | /* |
| 583 | * HTT Tx Desc is in uncached memory. Used cached writes per word, to |
| 584 | * reduce unnecessary memory access. |
| 585 | */ |
| 586 | |
| 587 | local_word0 = 0; |
| 588 | if (msdu_info) { |
| 589 | HTT_H2T_MSG_TYPE_SET(local_word0, HTT_H2T_MSG_TYPE_TX_FRM); |
| 590 | HTT_TX_DESC_PKT_TYPE_SET(local_word0, pkt_type); |
| 591 | HTT_TX_DESC_PKT_SUBTYPE_SET(local_word0, pkt_subtype); |
| 592 | HTT_TX_DESC_VDEV_ID_SET(local_word0, msdu_info->info.vdev_id); |
| 593 | if (tx_ctrl && tx_ctrl->valid_tid) |
| 594 | HTT_TX_DESC_EXT_TID_SET(local_word0, tx_ctrl->ext_tid); |
| 595 | else |
| 596 | HTT_TX_DESC_EXT_TID_SET(local_word0, |
| 597 | msdu_info->info.ext_tid); |
| 598 | HTT_TX_DESC_EXTENSION_SET(local_word0, desc_ext_required); |
| 599 | HTT_TX_DESC_EXT_TID_SET(local_word0, msdu_info->info.ext_tid); |
| 600 | HTT_TX_DESC_CKSUM_OFFLOAD_SET(local_word0, |
| 601 | msdu_info->action.cksum_offload); |
| 602 | HTT_TX_DESC_NO_ENCRYPT_SET(local_word0, |
| 603 | msdu_info->action.do_encrypt ? |
| 604 | 0 : 1); |
| 605 | } |
| 606 | |
| 607 | *word0 = local_word0; |
| 608 | |
| 609 | local_word1 = 0; |
| 610 | |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 611 | if (tso_info->is_tso) |
| 612 | HTT_TX_DESC_FRM_LEN_SET(local_word1, tso_info->total_len); |
| 613 | else |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 614 | HTT_TX_DESC_FRM_LEN_SET(local_word1, qdf_nbuf_len(msdu)); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 615 | |
| 616 | HTT_TX_DESC_FRM_ID_SET(local_word1, msdu_id); |
| 617 | *word1 = local_word1; |
| 618 | |
| 619 | /* Initialize peer_id to INVALID_PEER because |
| 620 | this is NOT Reinjection path */ |
| 621 | local_word3 = HTT_INVALID_PEER; |
| 622 | if (tx_ctrl && tx_ctrl->channel_freq) |
| 623 | HTT_TX_DESC_CHAN_FREQ_SET(local_word3, tx_ctrl->channel_freq); |
| 624 | #if HTT_PADDR64 |
| 625 | *word4 = local_word3; |
| 626 | #else /* ! HTT_PADDR64 */ |
| 627 | *word3 = local_word3; |
| 628 | #endif /* HTT_PADDR64 */ |
| 629 | |
| 630 | /* |
| 631 | * If any of the tx control flags are set, then we need the extended |
| 632 | * HTT header. |
| 633 | */ |
| 634 | if (desc_ext_required) { |
| 635 | struct htt_tx_msdu_desc_ext_t local_desc_ext = {0}; |
| 636 | |
| 637 | /* |
| 638 | * Copy the info that was read from TX control header from the |
| 639 | * user application to the extended HTT header. |
| 640 | * First copy everything |
| 641 | * to a local temp structure, and then copy everything to the |
| 642 | * actual uncached structure in one go to save memory writes. |
| 643 | */ |
| 644 | local_desc_ext.valid_pwr = tx_ctrl->valid_pwr; |
| 645 | local_desc_ext.valid_mcs_mask = tx_ctrl->valid_datarate; |
| 646 | local_desc_ext.valid_retries = tx_ctrl->valid_retries; |
| 647 | local_desc_ext.valid_expire_tsf = tx_ctrl->valid_expire_tsf; |
| 648 | local_desc_ext.valid_chainmask = tx_ctrl->valid_chain_mask; |
| 649 | |
| 650 | local_desc_ext.pwr = tx_ctrl->pwr; |
| 651 | if (tx_ctrl->valid_datarate && |
| 652 | tx_ctrl->datarate <= htt_ofdm_datarate_max) |
| 653 | local_desc_ext.mcs_mask = |
| 654 | (1 << (tx_ctrl->datarate + 4)); |
| 655 | local_desc_ext.retry_limit = tx_ctrl->retry_limit; |
| 656 | local_desc_ext.expire_tsf_lo = tx_ctrl->expire_tsf_lo; |
| 657 | local_desc_ext.expire_tsf_hi = tx_ctrl->expire_tsf_hi; |
| 658 | local_desc_ext.chain_mask = tx_ctrl->chain_mask; |
| 659 | |
| 660 | local_desc_ext.is_dsrc = (is_dsrc != 0); |
| 661 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 662 | qdf_nbuf_push_head(msdu, sizeof(local_desc_ext)); |
| 663 | qdf_mem_copy(qdf_nbuf_data(msdu), &local_desc_ext, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 664 | sizeof(local_desc_ext)); |
| 665 | } |
| 666 | |
| 667 | /* |
| 668 | * Specify that the data provided by the OS is a bytestream, |
| 669 | * and thus should not be byte-swapped during the HIF download |
| 670 | * even if the host is big-endian. |
| 671 | * There could be extra fragments added before the OS's fragments, |
| 672 | * e.g. for TSO, so it's incorrect to clear the frag 0 wordstream flag. |
| 673 | * Instead, clear the wordstream flag for the final fragment, which |
| 674 | * is certain to be (one of the) fragment(s) provided by the OS. |
| 675 | * Setting the flag for this final fragment suffices for specifying |
| 676 | * all fragments provided by the OS rather than added by the driver. |
| 677 | */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 678 | qdf_nbuf_set_frag_is_wordstream(msdu, qdf_nbuf_get_num_frags(msdu) - 1, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 679 | 0); |
| 680 | |
| 681 | /* store a link to the HTT tx descriptor within the netbuf */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 682 | qdf_nbuf_frag_push_head(msdu, sizeof(struct htt_host_tx_desc_t), |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 683 | (char *)htt_host_tx_desc, /* virtual addr */ |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 684 | htt_tx_desc_paddr); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 685 | |
| 686 | /* |
| 687 | * Indicate that the HTT header (and HTC header) is a meta-data |
| 688 | * "wordstream", i.e. series of uint32_t, rather than a data |
| 689 | * bytestream. |
| 690 | * This allows the HIF download to byteswap the HTT + HTC headers if |
| 691 | * the host is big-endian, to convert to the target's little-endian |
| 692 | * format. |
| 693 | */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 694 | qdf_nbuf_set_frag_is_wordstream(msdu, 0, 1); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 695 | |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 696 | if (qdf_likely(pdev->cfg.ce_classify_enabled && |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 697 | (msdu_info->info.l2_hdr_type != htt_pkt_type_mgmt))) { |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 698 | uint32_t pkt_offset = qdf_nbuf_get_frag_len(msdu, 0); |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 699 | data_attr = hw_classify << QDF_CE_TX_CLASSIFY_BIT_S; |
| 700 | data_attr |= ce_pkt_type << QDF_CE_TX_PKT_TYPE_BIT_S; |
| 701 | data_attr |= pkt_offset << QDF_CE_TX_PKT_OFFSET_BIT_S; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 702 | } |
| 703 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 704 | qdf_nbuf_data_attr_set(msdu, data_attr); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 705 | } |
| 706 | |
| 707 | /** |
| 708 | * @brief Set a flag to indicate that the MSDU in question was postponed. |
| 709 | * @details |
| 710 | * In systems in which the host retains its tx frame until the target sends |
| 711 | * a tx completion, the target has the option of discarding it's copy of |
| 712 | * the tx descriptor (and frame, for HL) and sending a "postpone" message |
| 713 | * to the host, to inform the host that it must eventually download the |
| 714 | * tx descriptor (and frame, for HL). |
| 715 | * Before the host downloads the postponed tx desc/frame again, it will use |
| 716 | * this function to set a flag in the HTT tx descriptor indicating that this |
| 717 | * is a re-send of a postponed frame, rather than a new frame. The target |
| 718 | * uses this flag to keep the correct order between re-sent and new tx frames. |
| 719 | * This function is relevant for LL systems. |
| 720 | * |
| 721 | * @param pdev - the handle of the physical device sending the tx data |
| 722 | * @param desc - abstract handle to the tx descriptor |
| 723 | */ |
| 724 | void htt_tx_desc_flag_postponed(htt_pdev_handle pdev, void *desc); |
| 725 | |
| 726 | /** |
| 727 | * @brief Set a flag to tell the target that more tx downloads are en route. |
| 728 | * @details |
| 729 | * At times, particularly in response to a U-APSD trigger in a HL system, the |
| 730 | * host will download multiple tx descriptors (+ frames, in HL) in a batch. |
| 731 | * The host will use this function to set a "more" flag in the initial |
| 732 | * and interior frames of the batch, to tell the target that more tx frame |
| 733 | * downloads within the batch are imminent. |
| 734 | * |
| 735 | * @param pdev - the handle of the physical device sending the tx data |
| 736 | * @param desc - abstract handle to the tx descriptor |
| 737 | */ |
| 738 | void htt_tx_desc_flag_batch_more(htt_pdev_handle pdev, void *desc); |
| 739 | |
| 740 | /** |
| 741 | * @brief Specify the number of fragments in the fragmentation descriptor. |
| 742 | * @details |
| 743 | * Specify the number of fragments within the MSDU, i.e. the number of |
| 744 | * elements within the fragmentation descriptor. |
| 745 | * For LL, this is used to terminate the list of fragments used by the |
| 746 | * HW's tx MAC DMA. |
| 747 | * For HL, this is used to terminate the list of fragments provided to |
| 748 | * HTC for download. |
| 749 | * |
| 750 | * @param pdev - the handle of the physical device sending the tx data |
| 751 | * @param desc - abstract handle to the tx descriptor |
| 752 | * @param num_frags - the number of fragments comprising the MSDU |
| 753 | */ |
| 754 | static inline |
| 755 | void |
| 756 | htt_tx_desc_num_frags(htt_pdev_handle pdev, void *desc, uint32_t num_frags) |
| 757 | { |
| 758 | /* |
| 759 | * Set the element after the valid frag elems to 0x0, |
| 760 | * to terminate the list of fragments. |
| 761 | */ |
| 762 | #if defined(HELIUMPLUS_PADDR64) |
| 763 | if (HTT_WIFI_IP(pdev, 2, 0)) { |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 764 | struct msdu_ext_frag_desc *fdesc; |
| 765 | |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 766 | /** Skip TSO related 4 dwords WIFI2.0*/ |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 767 | fdesc = (struct msdu_ext_frag_desc *) |
| 768 | &(((struct msdu_ext_desc_t *)desc)->frags[0]); |
| 769 | fdesc[num_frags].u.desc64 = 0; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 770 | } else { |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 771 | /* This piece of code should never be executed on HELIUMPLUS */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 772 | *((u_int32_t *) |
| 773 | (((char *) desc) + HTT_TX_DESC_LEN + num_frags * 8)) = 0; |
| 774 | } |
| 775 | #else /* ! HELIUMPLUS_PADDR64 */ |
| 776 | *((uint32_t *) |
| 777 | (((char *)desc) + HTT_TX_DESC_LEN + num_frags * 8)) = 0; |
| 778 | #endif /* HELIUMPLUS_PADDR64 */ |
| 779 | } |
| 780 | |
| 781 | /* checksum offload flags for hw */ |
| 782 | #define IPV4_CSUM_EN 0x00010000 |
| 783 | #define UDP_IPV4_CSUM_EN 0x00020000 |
| 784 | #define UDP_IPV6_CSUM_EN 0x00040000 |
| 785 | #define TCP_IPV4_CSUM_EN 0x00080000 |
| 786 | #define TCP_IPV6_CSUM_EN 0x00100000 |
| 787 | #define PARTIAL_CSUM_EN 0x00200000 |
| 788 | |
| 789 | /** |
| 790 | * @brief Specify the location and size of a fragment of a tx MSDU. |
| 791 | * @details |
| 792 | * In LL systems, the tx MAC DMA needs to know how the MSDU is constructed |
| 793 | * from fragments. |
| 794 | * In LL and HL systems, the HIF's download DMA to the target (LL: tx desc |
| 795 | * + header of tx payload; HL: tx desc + entire tx payload) needs to know |
| 796 | * where to find the fragments to download. |
| 797 | * The tx data SW uses this function to specify the location and size of |
| 798 | * each of the MSDU's fragments. |
| 799 | * |
| 800 | * @param pdev - the handle of the physical device sending the tx data |
| 801 | * @param desc - abstract handle to the HTT tx descriptor |
| 802 | * @param frag_num - which fragment is being specified (zero-based indexing) |
| 803 | * @param frag_phys_addr - DMA/physical address of the fragment |
| 804 | * @param frag_len - number of bytes within the fragment |
| 805 | */ |
| 806 | static inline |
| 807 | void |
| 808 | htt_tx_desc_frag(htt_pdev_handle pdev, |
| 809 | void *desc, |
Anurag Chouhan | df2b268 | 2016-02-29 14:15:27 +0530 | [diff] [blame] | 810 | int frag_num, qdf_dma_addr_t frag_phys_addr, uint16_t frag_len) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 811 | { |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 812 | uint32_t *word32; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 813 | #if defined(HELIUMPLUS_PADDR64) |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 814 | uint64_t *word64; |
| 815 | |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 816 | if (HTT_WIFI_IP(pdev, 2, 0)) { |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 817 | word32 = (u_int32_t *)(desc); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 818 | /* Initialize top 6 words of TSO flags per packet */ |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 819 | *word32++ = 0; |
| 820 | *word32++ = 0; |
| 821 | *word32++ = 0; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 822 | if (((struct txrx_pdev_cfg_t *)(pdev->ctrl_pdev)) |
| 823 | ->ip_tcp_udp_checksum_offload) |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 824 | *word32 |= (IPV4_CSUM_EN | TCP_IPV4_CSUM_EN | |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 825 | TCP_IPV6_CSUM_EN | UDP_IPV4_CSUM_EN | |
| 826 | UDP_IPV6_CSUM_EN); |
| 827 | else |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 828 | *word32 = 0; |
| 829 | word32++; |
| 830 | *word32++ = 0; |
| 831 | *word32++ = 0; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 832 | |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 833 | qdf_assert_always(word32 == (uint32_t *) |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 834 | &(((struct msdu_ext_desc_t *)desc)->frags[0])); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 835 | |
| 836 | /* Each fragment consumes 2 DWORDS */ |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 837 | word32 += (frag_num << 1); |
| 838 | word64 = (uint64_t *)word32; |
| 839 | *word64 = frag_phys_addr; |
| 840 | /* The frag_phys address is 37 bits. So, the higher 16 bits will be |
| 841 | for len */ |
| 842 | word32++; |
| 843 | *word32 &= 0x0000ffff; |
| 844 | *word32 |= (frag_len << 16); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 845 | } else { |
| 846 | /* For Helium+, this block cannot exist */ |
Anurag Chouhan | b2dc16f | 2016-02-25 11:47:37 +0530 | [diff] [blame] | 847 | QDF_ASSERT(0); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 848 | } |
| 849 | #else /* !defined(HELIUMPLUS_PADDR64) */ |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 850 | { |
| 851 | uint64_t u64 = (uint64_t)frag_phys_addr; |
| 852 | uint32_t u32l = (u64 & 0xffffffff); |
| 853 | uint32_t u32h = (uint32_t)((u64 >> 32) & 0x1f); |
| 854 | uint64_t *word64; |
| 855 | |
| 856 | word32 = (uint32_t *) (((char *)desc) + HTT_TX_DESC_LEN + frag_num * 8); |
| 857 | word64 = (uint64_t *)word32; |
| 858 | *word32 = u32l; |
| 859 | word32++; |
| 860 | *word32 = (u32h << 16) | frag_len; |
| 861 | } |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 862 | #endif /* defined(HELIUMPLUS_PADDR64) */ |
| 863 | } |
| 864 | |
| 865 | void htt_tx_desc_frags_table_set(htt_pdev_handle pdev, |
| 866 | void *desc, |
Anurag Chouhan | df2b268 | 2016-02-29 14:15:27 +0530 | [diff] [blame] | 867 | qdf_dma_addr_t paddr, |
| 868 | qdf_dma_addr_t frag_desc_paddr, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 869 | int reset); |
| 870 | |
| 871 | /** |
| 872 | * @brief Specify the type and subtype of a tx frame. |
| 873 | * |
| 874 | * @param pdev - the handle of the physical device sending the tx data |
| 875 | * @param type - format of the MSDU (802.3, native WiFi, raw, or mgmt) |
| 876 | * @param sub_type - sub_type (relevant for raw frames) |
| 877 | */ |
| 878 | static inline |
| 879 | void |
| 880 | htt_tx_desc_type(htt_pdev_handle pdev, |
| 881 | void *htt_tx_desc, enum wlan_frm_fmt type, uint8_t sub_type) |
| 882 | { |
| 883 | uint32_t *word0; |
| 884 | |
| 885 | word0 = (uint32_t *) htt_tx_desc; |
| 886 | /* clear old values */ |
| 887 | *word0 &= ~(HTT_TX_DESC_PKT_TYPE_M | HTT_TX_DESC_PKT_SUBTYPE_M); |
| 888 | /* write new values */ |
| 889 | HTT_TX_DESC_PKT_TYPE_SET(*word0, type); |
| 890 | HTT_TX_DESC_PKT_SUBTYPE_SET(*word0, sub_type); |
| 891 | } |
| 892 | |
| 893 | /***** TX MGMT DESC management APIs ****/ |
| 894 | |
| 895 | /* Number of mgmt descriptors in the pool */ |
| 896 | #define HTT_MAX_NUM_MGMT_DESCS 32 |
| 897 | |
| 898 | /** htt_tx_mgmt_desc_pool_alloc |
| 899 | * @description - allocates the memory for mgmt frame descriptors |
| 900 | * @param - htt pdev object |
| 901 | * @param - num of descriptors to be allocated in the pool |
| 902 | */ |
| 903 | void htt_tx_mgmt_desc_pool_alloc(struct htt_pdev_t *pdev, A_UINT32 num_elems); |
| 904 | |
| 905 | /** htt_tx_mgmt_desc_alloc |
| 906 | * @description - reserves a mgmt descriptor from the pool |
| 907 | * @param - htt pdev object |
| 908 | * @param - pointer to variable to hold the allocated desc id |
| 909 | * @param - pointer to the mamangement from UMAC |
| 910 | * @return - pointer the allocated mgmt descriptor |
| 911 | */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 912 | qdf_nbuf_t |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 913 | htt_tx_mgmt_desc_alloc(struct htt_pdev_t *pdev, A_UINT32 *desc_id, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 914 | qdf_nbuf_t mgmt_frm); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 915 | |
| 916 | /** htt_tx_mgmt_desc_free |
| 917 | * @description - releases the management descriptor back to the pool |
| 918 | * @param - htt pdev object |
| 919 | * @param - descriptor ID |
| 920 | */ |
| 921 | void |
| 922 | htt_tx_mgmt_desc_free(struct htt_pdev_t *pdev, A_UINT8 desc_id, |
| 923 | A_UINT32 status); |
| 924 | |
| 925 | /** htt_tx_mgmt_desc_pool_free |
| 926 | * @description - releases all the resources allocated for mgmt desc pool |
| 927 | * @param - htt pdev object |
| 928 | */ |
| 929 | void htt_tx_mgmt_desc_pool_free(struct htt_pdev_t *pdev); |
| 930 | |
| 931 | /** |
| 932 | * @brief Provide a buffer to store a 802.11 header added by SW tx encap |
| 933 | * |
| 934 | * @param htt_tx_desc - which frame the 802.11 header is being added to |
| 935 | * @param new_l2_hdr_size - how large the buffer needs to be |
| 936 | */ |
| 937 | #define htt_tx_desc_mpdu_header(htt_tx_desc, new_l2_hdr_size) /*NULL*/ |
| 938 | /** |
| 939 | * @brief How many tx credits would be consumed by the specified tx frame. |
| 940 | * |
| 941 | * @param msdu - the tx frame in question |
| 942 | * @return number of credits used for this tx frame |
| 943 | */ |
| 944 | #define htt_tx_msdu_credit(msdu) 1 /* 1 credit per buffer */ |
| 945 | #ifdef HTT_DBG |
| 946 | void htt_tx_desc_display(void *tx_desc); |
| 947 | #else |
| 948 | #define htt_tx_desc_display(tx_desc) |
| 949 | #endif |
| 950 | |
| 951 | static inline void htt_tx_desc_set_peer_id(void *htt_tx_desc, uint16_t peer_id) |
| 952 | { |
| 953 | uint16_t *peer_id_field_ptr; |
| 954 | |
| 955 | peer_id_field_ptr = (uint16_t *) |
| 956 | (htt_tx_desc + |
| 957 | HTT_TX_DESC_PEERID_DESC_PADDR_OFFSET_BYTES); |
| 958 | |
| 959 | *peer_id_field_ptr = peer_id; |
| 960 | } |
| 961 | |
| 962 | static inline |
| 963 | void htt_tx_desc_set_chanfreq(void *htt_tx_desc, uint16_t chanfreq) |
| 964 | { |
| 965 | uint16_t *chanfreq_field_ptr; |
| 966 | |
| 967 | /* The reason we dont use CHAN_FREQ_OFFSET_BYTES is because |
| 968 | it uses DWORD as unit */ |
| 969 | /* The reason we dont use the SET macro in htt.h is because |
| 970 | htt_tx_desc is incomplete type */ |
| 971 | chanfreq_field_ptr = (uint16_t *) |
| 972 | (htt_tx_desc + |
| 973 | HTT_TX_DESC_PEERID_DESC_PADDR_OFFSET_BYTES |
| 974 | + sizeof(A_UINT16)); |
| 975 | |
| 976 | *chanfreq_field_ptr = chanfreq; |
| 977 | } |
| 978 | |
| 979 | #if defined(FEATURE_TSO) |
| 980 | void |
| 981 | htt_tx_desc_fill_tso_info(htt_pdev_handle pdev, void *desc, |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 982 | struct qdf_tso_info_t *tso_info); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 983 | #else |
| 984 | #define htt_tx_desc_fill_tso_info(pdev, desc, tso_info) |
| 985 | #endif |
| 986 | #endif /* _OL_HTT_TX_API__H_ */ |