Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 1 | /* |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [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 htt_t2h.c |
| 30 | * @brief Provide functions to process target->host HTT messages. |
| 31 | * @details |
| 32 | * This file contains functions related to target->host HTT messages. |
| 33 | * There are two categories of functions: |
| 34 | * 1. A function that receives a HTT message from HTC, and dispatches it |
| 35 | * based on the HTT message type. |
| 36 | * 2. functions that provide the info elements from specific HTT messages. |
| 37 | */ |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 38 | #include <wma.h> |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 39 | #include <htc_api.h> /* HTC_PACKET */ |
| 40 | #include <htt.h> /* HTT_T2H_MSG_TYPE, etc. */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 41 | #include <qdf_nbuf.h> /* qdf_nbuf_t */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 42 | |
| 43 | #include <ol_htt_rx_api.h> |
| 44 | #include <ol_htt_tx_api.h> |
| 45 | #include <ol_txrx_htt_api.h> /* htt_tx_status */ |
| 46 | |
| 47 | #include <htt_internal.h> /* HTT_TX_SCHED, etc. */ |
| 48 | #include <pktlog_ac_fmt.h> |
| 49 | #include <wdi_event.h> |
| 50 | #include <ol_htt_tx_api.h> |
| 51 | #include <ol_txrx_types.h> |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 52 | #include <ol_txrx_peer_find.h> |
| 53 | |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 54 | /*--- target->host HTT message dispatch function ----------------------------*/ |
| 55 | |
| 56 | #ifndef DEBUG_CREDIT |
| 57 | #define DEBUG_CREDIT 0 |
| 58 | #endif |
| 59 | |
| 60 | static uint8_t *htt_t2h_mac_addr_deswizzle(uint8_t *tgt_mac_addr, |
| 61 | uint8_t *buffer) |
| 62 | { |
| 63 | #ifdef BIG_ENDIAN_HOST |
| 64 | /* |
| 65 | * The host endianness is opposite of the target endianness. |
| 66 | * To make uint32_t elements come out correctly, the target->host |
| 67 | * upload has swizzled the bytes in each uint32_t element of the |
| 68 | * message. |
| 69 | * For byte-array message fields like the MAC address, this |
| 70 | * upload swizzling puts the bytes in the wrong order, and needs |
| 71 | * to be undone. |
| 72 | */ |
| 73 | buffer[0] = tgt_mac_addr[3]; |
| 74 | buffer[1] = tgt_mac_addr[2]; |
| 75 | buffer[2] = tgt_mac_addr[1]; |
| 76 | buffer[3] = tgt_mac_addr[0]; |
| 77 | buffer[4] = tgt_mac_addr[7]; |
| 78 | buffer[5] = tgt_mac_addr[6]; |
| 79 | return buffer; |
| 80 | #else |
| 81 | /* |
| 82 | * The host endianness matches the target endianness - |
| 83 | * we can use the mac addr directly from the message buffer. |
| 84 | */ |
| 85 | return tgt_mac_addr; |
| 86 | #endif |
| 87 | } |
| 88 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 89 | static void htt_rx_frag_set_last_msdu(struct htt_pdev_t *pdev, qdf_nbuf_t msg) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 90 | { |
| 91 | uint32_t *msg_word; |
| 92 | unsigned num_msdu_bytes; |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 93 | qdf_nbuf_t msdu; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 94 | struct htt_host_rx_desc_base *rx_desc; |
| 95 | int start_idx; |
| 96 | uint8_t *p_fw_msdu_rx_desc = 0; |
| 97 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 98 | msg_word = (uint32_t *) qdf_nbuf_data(msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 99 | num_msdu_bytes = HTT_RX_FRAG_IND_FW_RX_DESC_BYTES_GET( |
| 100 | *(msg_word + HTT_RX_FRAG_IND_HDR_PREFIX_SIZE32)); |
| 101 | /* |
| 102 | * 1 word for the message header, |
| 103 | * 1 word to specify the number of MSDU bytes, |
| 104 | * 1 word for every 4 MSDU bytes (round up), |
| 105 | * 1 word for the MPDU range header |
| 106 | */ |
| 107 | pdev->rx_mpdu_range_offset_words = 3 + ((num_msdu_bytes + 3) >> 2); |
| 108 | pdev->rx_ind_msdu_byte_idx = 0; |
| 109 | |
| 110 | p_fw_msdu_rx_desc = ((uint8_t *) (msg_word) + |
| 111 | HTT_ENDIAN_BYTE_IDX_SWAP |
| 112 | (HTT_RX_FRAG_IND_FW_DESC_BYTE_OFFSET)); |
| 113 | |
| 114 | /* |
| 115 | * Fix for EV126710, in which BSOD occurs due to last_msdu bit |
| 116 | * not set while the next pointer is deliberately set to NULL |
| 117 | * before calling ol_rx_pn_check_base() |
| 118 | * |
| 119 | * For fragment frames, the HW may not have set the last_msdu bit |
| 120 | * in the rx descriptor, but the SW expects this flag to be set, |
| 121 | * since each fragment is in a separate MPDU. Thus, set the flag here, |
| 122 | * just in case the HW didn't. |
| 123 | */ |
| 124 | start_idx = pdev->rx_ring.sw_rd_idx.msdu_payld; |
| 125 | msdu = pdev->rx_ring.buf.netbufs_ring[start_idx]; |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 126 | qdf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); |
| 127 | qdf_nbuf_unmap(pdev->osdev, msdu, QDF_DMA_FROM_DEVICE); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 128 | rx_desc = htt_rx_desc(msdu); |
| 129 | *((uint8_t *) &rx_desc->fw_desc.u.val) = *p_fw_msdu_rx_desc; |
| 130 | rx_desc->msdu_end.last_msdu = 1; |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 131 | qdf_nbuf_map(pdev->osdev, msdu, QDF_DMA_FROM_DEVICE); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 132 | } |
| 133 | |
| 134 | /* Target to host Msg/event handler for low priority messages*/ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 135 | void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 136 | { |
| 137 | struct htt_pdev_t *pdev = (struct htt_pdev_t *)context; |
| 138 | uint32_t *msg_word; |
| 139 | enum htt_t2h_msg_type msg_type; |
| 140 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 141 | msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 142 | msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); |
| 143 | switch (msg_type) { |
| 144 | case HTT_T2H_MSG_TYPE_VERSION_CONF: |
| 145 | { |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 146 | qdf_runtime_pm_put(); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 147 | pdev->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word); |
| 148 | pdev->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word); |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 149 | qdf_print |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 150 | ("target uses HTT version %d.%d; host uses %d.%d", |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 151 | pdev->tgt_ver.major, pdev->tgt_ver.minor, |
| 152 | HTT_CURRENT_VERSION_MAJOR, |
| 153 | HTT_CURRENT_VERSION_MINOR); |
| 154 | if (pdev->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 155 | qdf_print |
Houston Hoffman | 43d47fa | 2016-02-24 16:34:30 -0800 | [diff] [blame] | 156 | ("*** Incompatible host/target HTT versions!"); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 157 | /* abort if the target is incompatible with the host */ |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 158 | qdf_assert(pdev->tgt_ver.major == |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 159 | HTT_CURRENT_VERSION_MAJOR); |
| 160 | if (pdev->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 161 | qdf_print("*** Warning: host/target HTT versions are "); |
| 162 | qdf_print(" different, though compatible!"); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 163 | } |
| 164 | break; |
| 165 | } |
| 166 | case HTT_T2H_MSG_TYPE_RX_FLUSH: |
| 167 | { |
| 168 | uint16_t peer_id; |
| 169 | uint8_t tid; |
| 170 | int seq_num_start, seq_num_end; |
| 171 | enum htt_rx_flush_action action; |
| 172 | |
| 173 | peer_id = HTT_RX_FLUSH_PEER_ID_GET(*msg_word); |
| 174 | tid = HTT_RX_FLUSH_TID_GET(*msg_word); |
| 175 | seq_num_start = |
| 176 | HTT_RX_FLUSH_SEQ_NUM_START_GET(*(msg_word + 1)); |
| 177 | seq_num_end = |
| 178 | HTT_RX_FLUSH_SEQ_NUM_END_GET(*(msg_word + 1)); |
| 179 | action = |
| 180 | HTT_RX_FLUSH_MPDU_STATUS_GET(*(msg_word + 1)) == |
| 181 | 1 ? htt_rx_flush_release : htt_rx_flush_discard; |
| 182 | ol_rx_flush_handler(pdev->txrx_pdev, peer_id, tid, |
| 183 | seq_num_start, seq_num_end, action); |
| 184 | break; |
| 185 | } |
| 186 | case HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND: |
| 187 | { |
| 188 | int msdu_cnt; |
| 189 | msdu_cnt = |
| 190 | HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_GET(*msg_word); |
| 191 | ol_rx_offload_deliver_ind_handler(pdev->txrx_pdev, |
| 192 | htt_t2h_msg, |
| 193 | msdu_cnt); |
| 194 | break; |
| 195 | } |
| 196 | case HTT_T2H_MSG_TYPE_RX_FRAG_IND: |
| 197 | { |
| 198 | uint16_t peer_id; |
| 199 | uint8_t tid; |
| 200 | |
| 201 | peer_id = HTT_RX_FRAG_IND_PEER_ID_GET(*msg_word); |
| 202 | tid = HTT_RX_FRAG_IND_EXT_TID_GET(*msg_word); |
| 203 | htt_rx_frag_set_last_msdu(pdev, htt_t2h_msg); |
| 204 | |
| 205 | ol_rx_frag_indication_handler(pdev->txrx_pdev, |
| 206 | htt_t2h_msg, |
| 207 | peer_id, tid); |
| 208 | break; |
| 209 | } |
| 210 | case HTT_T2H_MSG_TYPE_RX_ADDBA: |
| 211 | { |
| 212 | uint16_t peer_id; |
| 213 | uint8_t tid; |
| 214 | uint8_t win_sz; |
| 215 | uint16_t start_seq_num; |
| 216 | |
| 217 | /* |
| 218 | * FOR NOW, the host doesn't need to know the initial |
| 219 | * sequence number for rx aggregation. |
| 220 | * Thus, any value will do - specify 0. |
| 221 | */ |
| 222 | start_seq_num = 0; |
| 223 | peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word); |
| 224 | tid = HTT_RX_ADDBA_TID_GET(*msg_word); |
| 225 | win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word); |
| 226 | ol_rx_addba_handler(pdev->txrx_pdev, peer_id, tid, |
| 227 | win_sz, start_seq_num, |
| 228 | 0 /* success */); |
| 229 | break; |
| 230 | } |
| 231 | case HTT_T2H_MSG_TYPE_RX_DELBA: |
| 232 | { |
| 233 | uint16_t peer_id; |
| 234 | uint8_t tid; |
| 235 | |
| 236 | peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word); |
| 237 | tid = HTT_RX_DELBA_TID_GET(*msg_word); |
| 238 | ol_rx_delba_handler(pdev->txrx_pdev, peer_id, tid); |
| 239 | break; |
| 240 | } |
| 241 | case HTT_T2H_MSG_TYPE_PEER_MAP: |
| 242 | { |
| 243 | uint8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; |
| 244 | uint8_t *peer_mac_addr; |
| 245 | uint16_t peer_id; |
| 246 | uint8_t vdev_id; |
| 247 | |
| 248 | peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word); |
| 249 | vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word); |
| 250 | peer_mac_addr = htt_t2h_mac_addr_deswizzle( |
| 251 | (uint8_t *) (msg_word + 1), |
| 252 | &mac_addr_deswizzle_buf[0]); |
| 253 | |
| 254 | ol_rx_peer_map_handler(pdev->txrx_pdev, peer_id, |
| 255 | vdev_id, peer_mac_addr, |
| 256 | 1 /*can tx */); |
| 257 | break; |
| 258 | } |
| 259 | case HTT_T2H_MSG_TYPE_PEER_UNMAP: |
| 260 | { |
| 261 | uint16_t peer_id; |
| 262 | peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word); |
| 263 | |
| 264 | ol_rx_peer_unmap_handler(pdev->txrx_pdev, peer_id); |
| 265 | break; |
| 266 | } |
| 267 | case HTT_T2H_MSG_TYPE_SEC_IND: |
| 268 | { |
| 269 | uint16_t peer_id; |
| 270 | enum htt_sec_type sec_type; |
| 271 | int is_unicast; |
| 272 | |
| 273 | peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word); |
| 274 | sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word); |
| 275 | is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word); |
| 276 | msg_word++; /* point to the first part of the Michael key */ |
| 277 | ol_rx_sec_ind_handler(pdev->txrx_pdev, peer_id, |
| 278 | sec_type, is_unicast, msg_word, |
| 279 | msg_word + 2); |
| 280 | break; |
| 281 | } |
| 282 | case HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND: |
| 283 | { |
| 284 | struct htt_mgmt_tx_compl_ind *compl_msg; |
| 285 | |
| 286 | compl_msg = |
| 287 | (struct htt_mgmt_tx_compl_ind *)(msg_word + 1); |
| 288 | |
Nirav Shah | f2e3637 | 2015-12-10 15:42:17 +0530 | [diff] [blame] | 289 | if (!ol_tx_get_is_mgmt_over_wmi_enabled()) { |
| 290 | ol_tx_single_completion_handler(pdev->txrx_pdev, |
| 291 | compl_msg->status, |
| 292 | compl_msg->desc_id); |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 293 | qdf_runtime_pm_put(); |
Nirav Shah | f2e3637 | 2015-12-10 15:42:17 +0530 | [diff] [blame] | 294 | HTT_TX_SCHED(pdev); |
| 295 | } else { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 296 | qdf_print("Ignoring HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND indication"); |
Nirav Shah | f2e3637 | 2015-12-10 15:42:17 +0530 | [diff] [blame] | 297 | } |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 298 | break; |
| 299 | } |
| 300 | case HTT_T2H_MSG_TYPE_STATS_CONF: |
| 301 | { |
| 302 | uint64_t cookie; |
| 303 | uint8_t *stats_info_list; |
| 304 | |
| 305 | cookie = *(msg_word + 1); |
| 306 | cookie |= ((uint64_t) (*(msg_word + 2))) << 32; |
| 307 | |
| 308 | stats_info_list = (uint8_t *) (msg_word + 3); |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 309 | qdf_runtime_pm_put(); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 310 | ol_txrx_fw_stats_handler(pdev->txrx_pdev, cookie, |
| 311 | stats_info_list); |
| 312 | break; |
| 313 | } |
| 314 | #ifndef REMOVE_PKT_LOG |
| 315 | case HTT_T2H_MSG_TYPE_PKTLOG: |
| 316 | { |
| 317 | uint32_t *pl_hdr; |
| 318 | uint32_t log_type; |
| 319 | pl_hdr = (msg_word + 1); |
| 320 | log_type = |
| 321 | (*(pl_hdr + 1) & ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> |
| 322 | ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; |
| 323 | if ((log_type == PKTLOG_TYPE_TX_CTRL) |
| 324 | || (log_type == PKTLOG_TYPE_TX_STAT) |
| 325 | || (log_type == PKTLOG_TYPE_TX_MSDU_ID) |
| 326 | || (log_type == PKTLOG_TYPE_TX_FRM_HDR) |
| 327 | || (log_type == PKTLOG_TYPE_TX_VIRT_ADDR)) |
| 328 | wdi_event_handler(WDI_EVENT_TX_STATUS, |
| 329 | pdev->txrx_pdev, pl_hdr); |
| 330 | else if (log_type == PKTLOG_TYPE_RC_FIND) |
| 331 | wdi_event_handler(WDI_EVENT_RATE_FIND, |
| 332 | pdev->txrx_pdev, pl_hdr); |
| 333 | else if (log_type == PKTLOG_TYPE_RC_UPDATE) |
| 334 | wdi_event_handler(WDI_EVENT_RATE_UPDATE, |
| 335 | pdev->txrx_pdev, pl_hdr); |
| 336 | else if (log_type == PKTLOG_TYPE_RX_STAT) |
| 337 | wdi_event_handler(WDI_EVENT_RX_DESC, |
| 338 | pdev->txrx_pdev, pl_hdr); |
| 339 | |
| 340 | break; |
| 341 | } |
| 342 | #endif |
| 343 | case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND: |
| 344 | { |
| 345 | uint32_t htt_credit_delta_abs; |
| 346 | int32_t htt_credit_delta; |
| 347 | int sign; |
| 348 | |
| 349 | htt_credit_delta_abs = |
| 350 | HTT_TX_CREDIT_DELTA_ABS_GET(*msg_word); |
| 351 | sign = HTT_TX_CREDIT_SIGN_BIT_GET(*msg_word) ? -1 : 1; |
| 352 | htt_credit_delta = sign * htt_credit_delta_abs; |
| 353 | ol_tx_credit_completion_handler(pdev->txrx_pdev, |
| 354 | htt_credit_delta); |
| 355 | break; |
| 356 | } |
| 357 | |
| 358 | case HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE: |
| 359 | { |
| 360 | uint8_t op_code; |
| 361 | uint16_t len; |
| 362 | uint8_t *op_msg_buffer; |
| 363 | uint8_t *msg_start_ptr; |
| 364 | |
Anurag Chouhan | a37b5b7 | 2016-02-21 14:53:42 +0530 | [diff] [blame] | 365 | qdf_runtime_pm_put(); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 366 | msg_start_ptr = (uint8_t *) msg_word; |
| 367 | op_code = |
| 368 | HTT_WDI_IPA_OP_RESPONSE_OP_CODE_GET(*msg_word); |
| 369 | msg_word++; |
| 370 | len = HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_GET(*msg_word); |
| 371 | |
| 372 | op_msg_buffer = |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame] | 373 | qdf_mem_malloc(sizeof |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 374 | (struct htt_wdi_ipa_op_response_t) + |
| 375 | len); |
| 376 | if (!op_msg_buffer) { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 377 | qdf_print("OPCODE messsage buffer alloc fail"); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 378 | break; |
| 379 | } |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame] | 380 | qdf_mem_copy(op_msg_buffer, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 381 | msg_start_ptr, |
| 382 | sizeof(struct htt_wdi_ipa_op_response_t) + |
| 383 | len); |
| 384 | ol_txrx_ipa_uc_op_response(pdev->txrx_pdev, |
| 385 | op_msg_buffer); |
| 386 | break; |
| 387 | } |
| 388 | |
| 389 | case HTT_T2H_MSG_TYPE_FLOW_POOL_MAP: |
| 390 | { |
| 391 | uint8_t num_flows; |
| 392 | struct htt_flow_pool_map_payload_t *pool_map_payoad; |
| 393 | |
| 394 | num_flows = HTT_FLOW_POOL_MAP_NUM_FLOWS_GET(*msg_word); |
| 395 | |
| 396 | msg_word++; |
| 397 | while (num_flows) { |
| 398 | pool_map_payoad = (struct htt_flow_pool_map_payload_t *) |
| 399 | msg_word; |
| 400 | ol_tx_flow_pool_map_handler(pool_map_payoad->flow_id, |
| 401 | pool_map_payoad->flow_type, |
| 402 | pool_map_payoad->flow_pool_id, |
| 403 | pool_map_payoad->flow_pool_size); |
| 404 | |
| 405 | msg_word += (HTT_FLOW_POOL_MAP_PAYLOAD_SZ / |
| 406 | HTT_FLOW_POOL_MAP_HEADER_SZ); |
| 407 | num_flows--; |
| 408 | } |
| 409 | break; |
| 410 | } |
| 411 | |
| 412 | case HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP: |
| 413 | { |
| 414 | struct htt_flow_pool_unmap_t *pool_numap_payload; |
| 415 | |
| 416 | pool_numap_payload = (struct htt_flow_pool_unmap_t *)msg_word; |
| 417 | ol_tx_flow_pool_unmap_handler(pool_numap_payload->flow_id, |
| 418 | pool_numap_payload->flow_type, |
| 419 | pool_numap_payload->flow_pool_id); |
| 420 | break; |
| 421 | } |
| 422 | |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 423 | case HTT_T2H_MSG_TYPE_RX_OFLD_PKT_ERR: |
| 424 | { |
| 425 | switch (HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_GET(*msg_word)) { |
| 426 | case HTT_RX_OFLD_PKT_ERR_TYPE_MIC_ERR: |
| 427 | { |
| 428 | struct ol_error_info err_info; |
| 429 | struct ol_txrx_vdev_t *vdev; |
| 430 | struct ol_txrx_peer_t *peer; |
| 431 | uint16_t peer_id = |
| 432 | HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_GET |
| 433 | (*(msg_word + 1)); |
| 434 | |
| 435 | peer = ol_txrx_peer_find_by_id(pdev->txrx_pdev, |
| 436 | peer_id); |
| 437 | if (!peer) { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 438 | qdf_print("%s: invalid peer id %d\n", |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 439 | __func__, peer_id); |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 440 | qdf_assert(0); |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 441 | break; |
| 442 | } |
| 443 | vdev = peer->vdev; |
| 444 | err_info.u.mic_err.vdev_id = vdev->vdev_id; |
| 445 | err_info.u.mic_err.key_id = |
| 446 | HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_GET |
| 447 | (*(msg_word + 1)); |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame] | 448 | qdf_mem_copy(err_info.u.mic_err.da, |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 449 | (uint8_t *)(msg_word + 2), |
| 450 | OL_TXRX_MAC_ADDR_LEN); |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame] | 451 | qdf_mem_copy(err_info.u.mic_err.sa, |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 452 | (uint8_t *)(msg_word + 4), |
| 453 | OL_TXRX_MAC_ADDR_LEN); |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame] | 454 | qdf_mem_copy(&err_info.u.mic_err.pn, |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 455 | (uint8_t *)(msg_word + 6), 6); |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame] | 456 | qdf_mem_copy(err_info.u.mic_err.ta, |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 457 | peer->mac_addr.raw, OL_TXRX_MAC_ADDR_LEN); |
| 458 | |
| 459 | wma_indicate_err(OL_RX_ERR_TKIP_MIC, &err_info); |
| 460 | break; |
| 461 | } |
| 462 | default: |
| 463 | { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 464 | qdf_print("%s: unhandled error type %d\n", |
Dhanashri Atre | 1f0cbe4 | 2015-11-19 10:56:53 -0800 | [diff] [blame] | 465 | __func__, |
| 466 | HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_GET(*msg_word)); |
| 467 | break; |
| 468 | } |
| 469 | } |
| 470 | } |
| 471 | |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 472 | default: |
| 473 | break; |
| 474 | }; |
| 475 | /* Free the indication buffer */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 476 | qdf_nbuf_free(htt_t2h_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 477 | } |
| 478 | |
| 479 | /* Generic Target to host Msg/event handler for low priority messages |
| 480 | Low priority message are handler in a different handler called from |
| 481 | this function . So that the most likely succes path like Rx and |
| 482 | Tx comp has little code foot print |
| 483 | */ |
| 484 | void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) |
| 485 | { |
| 486 | struct htt_pdev_t *pdev = (struct htt_pdev_t *)context; |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 487 | qdf_nbuf_t htt_t2h_msg = (qdf_nbuf_t) pkt->pPktContext; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 488 | uint32_t *msg_word; |
| 489 | enum htt_t2h_msg_type msg_type; |
| 490 | |
| 491 | /* check for successful message reception */ |
| 492 | if (pkt->Status != A_OK) { |
| 493 | if (pkt->Status != A_ECANCELED) |
| 494 | pdev->stats.htc_err_cnt++; |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 495 | qdf_nbuf_free(htt_t2h_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 496 | return; |
| 497 | } |
| 498 | #ifdef HTT_RX_RESTORE |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 499 | if (qdf_unlikely(pdev->rx_ring.rx_reset)) { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 500 | qdf_print("rx restore ..\n"); |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 501 | qdf_nbuf_free(htt_t2h_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 502 | return; |
| 503 | } |
| 504 | #endif |
| 505 | |
| 506 | /* confirm alignment */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 507 | HTT_ASSERT3((((unsigned long)qdf_nbuf_data(htt_t2h_msg)) & 0x3) == 0); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 508 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 509 | msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 510 | msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); |
| 511 | |
| 512 | #if defined(HELIUMPLUS_DEBUG) |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 513 | qdf_print("%s %d: msg_word 0x%x msg_type %d", |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 514 | __func__, __LINE__, *msg_word, msg_type); |
| 515 | #endif |
| 516 | |
| 517 | switch (msg_type) { |
| 518 | case HTT_T2H_MSG_TYPE_RX_IND: |
| 519 | { |
| 520 | unsigned num_mpdu_ranges; |
| 521 | unsigned num_msdu_bytes; |
| 522 | uint16_t peer_id; |
| 523 | uint8_t tid; |
| 524 | |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 525 | if (qdf_unlikely(pdev->cfg.is_full_reorder_offload)) { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 526 | qdf_print("HTT_T2H_MSG_TYPE_RX_IND not supported "); |
| 527 | qdf_print("with full reorder offload\n"); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 528 | break; |
| 529 | } |
| 530 | peer_id = HTT_RX_IND_PEER_ID_GET(*msg_word); |
| 531 | tid = HTT_RX_IND_EXT_TID_GET(*msg_word); |
| 532 | |
DARAM SUDHA | e83cda6 | 2015-05-16 08:11:57 +0530 | [diff] [blame] | 533 | if (tid >= OL_TXRX_NUM_EXT_TIDS) { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 534 | qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid tid %d\n", |
DARAM SUDHA | e83cda6 | 2015-05-16 08:11:57 +0530 | [diff] [blame] | 535 | tid); |
| 536 | break; |
| 537 | } |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 538 | num_msdu_bytes = |
| 539 | HTT_RX_IND_FW_RX_DESC_BYTES_GET( |
| 540 | *(msg_word + 2 + HTT_RX_PPDU_DESC_SIZE32)); |
| 541 | /* |
| 542 | * 1 word for the message header, |
| 543 | * HTT_RX_PPDU_DESC_SIZE32 words for the FW rx PPDU desc |
| 544 | * 1 word to specify the number of MSDU bytes, |
| 545 | * 1 word for every 4 MSDU bytes (round up), |
| 546 | * 1 word for the MPDU range header |
| 547 | */ |
| 548 | pdev->rx_mpdu_range_offset_words = |
| 549 | (HTT_RX_IND_HDR_BYTES + num_msdu_bytes + 3) >> 2; |
| 550 | num_mpdu_ranges = |
| 551 | HTT_RX_IND_NUM_MPDU_RANGES_GET(*(msg_word + 1)); |
| 552 | pdev->rx_ind_msdu_byte_idx = 0; |
| 553 | |
| 554 | ol_rx_indication_handler(pdev->txrx_pdev, |
| 555 | htt_t2h_msg, peer_id, |
| 556 | tid, num_mpdu_ranges); |
| 557 | break; |
| 558 | } |
| 559 | case HTT_T2H_MSG_TYPE_TX_COMPL_IND: |
| 560 | { |
| 561 | int num_msdus; |
| 562 | enum htt_tx_status status; |
| 563 | |
| 564 | /* status - no enum translation needed */ |
| 565 | status = HTT_TX_COMPL_IND_STATUS_GET(*msg_word); |
| 566 | num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word); |
| 567 | if (num_msdus & 0x1) { |
| 568 | struct htt_tx_compl_ind_base *compl = |
| 569 | (void *)msg_word; |
| 570 | |
| 571 | /* |
| 572 | * Host CPU endianness can be different from FW CPU. |
| 573 | * This can result in even and odd MSDU IDs being |
| 574 | * switched. If this happens, copy the switched final |
| 575 | * odd MSDU ID from location payload[size], to |
| 576 | * location payload[size-1], where the message |
| 577 | * handler function expects to find it |
| 578 | */ |
| 579 | if (compl->payload[num_msdus] != |
| 580 | HTT_TX_COMPL_INV_MSDU_ID) { |
| 581 | compl->payload[num_msdus - 1] = |
| 582 | compl->payload[num_msdus]; |
| 583 | } |
| 584 | } |
| 585 | ol_tx_completion_handler(pdev->txrx_pdev, num_msdus, |
| 586 | status, msg_word + 1); |
| 587 | HTT_TX_SCHED(pdev); |
| 588 | break; |
| 589 | } |
| 590 | case HTT_T2H_MSG_TYPE_RX_PN_IND: |
| 591 | { |
| 592 | uint16_t peer_id; |
| 593 | uint8_t tid, pn_ie_cnt, *pn_ie = NULL; |
| 594 | int seq_num_start, seq_num_end; |
| 595 | |
| 596 | /*First dword */ |
| 597 | peer_id = HTT_RX_PN_IND_PEER_ID_GET(*msg_word); |
| 598 | tid = HTT_RX_PN_IND_EXT_TID_GET(*msg_word); |
| 599 | |
| 600 | msg_word++; |
| 601 | /*Second dword */ |
| 602 | seq_num_start = |
| 603 | HTT_RX_PN_IND_SEQ_NUM_START_GET(*msg_word); |
| 604 | seq_num_end = HTT_RX_PN_IND_SEQ_NUM_END_GET(*msg_word); |
| 605 | pn_ie_cnt = HTT_RX_PN_IND_PN_IE_CNT_GET(*msg_word); |
| 606 | |
| 607 | msg_word++; |
| 608 | /*Third dword */ |
| 609 | if (pn_ie_cnt) |
| 610 | pn_ie = (uint8_t *) msg_word; |
| 611 | |
| 612 | ol_rx_pn_ind_handler(pdev->txrx_pdev, peer_id, tid, |
| 613 | seq_num_start, seq_num_end, |
| 614 | pn_ie_cnt, pn_ie); |
| 615 | |
| 616 | break; |
| 617 | } |
| 618 | case HTT_T2H_MSG_TYPE_TX_INSPECT_IND: |
| 619 | { |
| 620 | int num_msdus; |
| 621 | |
| 622 | num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word); |
| 623 | if (num_msdus & 0x1) { |
| 624 | struct htt_tx_compl_ind_base *compl = |
| 625 | (void *)msg_word; |
| 626 | |
| 627 | /* |
| 628 | * Host CPU endianness can be different from FW CPU. |
| 629 | * This can result in even and odd MSDU IDs being |
| 630 | * switched. If this happens, copy the switched final |
| 631 | * odd MSDU ID from location payload[size], to |
| 632 | * location payload[size-1], where the message handler |
| 633 | * function expects to find it |
| 634 | */ |
| 635 | if (compl->payload[num_msdus] != |
| 636 | HTT_TX_COMPL_INV_MSDU_ID) { |
| 637 | compl->payload[num_msdus - 1] = |
| 638 | compl->payload[num_msdus]; |
| 639 | } |
| 640 | } |
| 641 | ol_tx_inspect_handler(pdev->txrx_pdev, num_msdus, |
| 642 | msg_word + 1); |
| 643 | HTT_TX_SCHED(pdev); |
| 644 | break; |
| 645 | } |
| 646 | case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: |
| 647 | { |
| 648 | uint16_t peer_id; |
| 649 | uint8_t tid; |
| 650 | uint8_t offload_ind, frag_ind; |
| 651 | |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 652 | if (qdf_unlikely(!pdev->cfg.is_full_reorder_offload)) { |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 653 | qdf_print("HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND not "); |
| 654 | qdf_print("supported when full reorder offload is "); |
| 655 | qdf_print("disabled in the configuration.\n"); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 656 | break; |
| 657 | } |
| 658 | |
| 659 | peer_id = HTT_RX_IN_ORD_PADDR_IND_PEER_ID_GET(*msg_word); |
| 660 | tid = HTT_RX_IN_ORD_PADDR_IND_EXT_TID_GET(*msg_word); |
| 661 | offload_ind = HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_GET(*msg_word); |
| 662 | frag_ind = HTT_RX_IN_ORD_PADDR_IND_FRAG_GET(*msg_word); |
| 663 | |
| 664 | #if defined(HELIUMPLUS_DEBUG) |
Anurag Chouhan | 6d76066 | 2016-02-20 16:05:43 +0530 | [diff] [blame] | 665 | qdf_print("%s %d: peerid %d tid %d offloadind %d fragind %d\n", |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 666 | __func__, __LINE__, peer_id, tid, offload_ind, |
| 667 | frag_ind); |
| 668 | #endif |
Anurag Chouhan | c554842 | 2016-02-24 18:33:27 +0530 | [diff] [blame] | 669 | if (qdf_unlikely(frag_ind)) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 670 | ol_rx_frag_indication_handler(pdev->txrx_pdev, |
| 671 | htt_t2h_msg, |
| 672 | peer_id, tid); |
| 673 | break; |
| 674 | } |
| 675 | |
| 676 | ol_rx_in_order_indication_handler(pdev->txrx_pdev, |
| 677 | htt_t2h_msg, peer_id, |
| 678 | tid, offload_ind); |
| 679 | break; |
| 680 | } |
| 681 | |
| 682 | default: |
| 683 | htt_t2h_lp_msg_handler(context, htt_t2h_msg); |
| 684 | return; |
| 685 | |
| 686 | }; |
| 687 | |
| 688 | /* Free the indication buffer */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 689 | qdf_nbuf_free(htt_t2h_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 690 | } |
| 691 | |
| 692 | /*--- target->host HTT message Info Element access methods ------------------*/ |
| 693 | |
| 694 | /*--- tx completion message ---*/ |
| 695 | |
| 696 | uint16_t htt_tx_compl_desc_id(void *iterator, int num) |
| 697 | { |
| 698 | /* |
| 699 | * The MSDU IDs are packed , 2 per 32-bit word. |
| 700 | * Iterate on them as an array of 16-bit elements. |
| 701 | * This will work fine if the host endianness matches |
| 702 | * the target endianness. |
| 703 | * If the host endianness is opposite of the target's, |
| 704 | * this iterator will produce descriptor IDs in a different |
| 705 | * order than the target inserted them into the message - |
| 706 | * if the target puts in [0, 1, 2, 3, ...] the host will |
| 707 | * put out [1, 0, 3, 2, ...]. |
| 708 | * This is fine, except for the last ID if there are an |
| 709 | * odd number of IDs. But the TX_COMPL_IND handling code |
| 710 | * in the htt_t2h_msg_handler already added a duplicate |
| 711 | * of the final ID, if there were an odd number of IDs, |
| 712 | * so this function can safely treat the IDs as an array |
| 713 | * of 16-bit elements. |
| 714 | */ |
| 715 | return *(((uint16_t *) iterator) + num); |
| 716 | } |
| 717 | |
| 718 | /*--- rx indication message ---*/ |
| 719 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 720 | int htt_rx_ind_flush(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 721 | { |
| 722 | uint32_t *msg_word; |
| 723 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 724 | msg_word = (uint32_t *) qdf_nbuf_data(rx_ind_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 725 | return HTT_RX_IND_FLUSH_VALID_GET(*msg_word); |
| 726 | } |
| 727 | |
| 728 | void |
| 729 | htt_rx_ind_flush_seq_num_range(htt_pdev_handle pdev, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 730 | qdf_nbuf_t rx_ind_msg, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 731 | unsigned *seq_num_start, unsigned *seq_num_end) |
| 732 | { |
| 733 | uint32_t *msg_word; |
| 734 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 735 | msg_word = (uint32_t *) qdf_nbuf_data(rx_ind_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 736 | msg_word++; |
| 737 | *seq_num_start = HTT_RX_IND_FLUSH_SEQ_NUM_START_GET(*msg_word); |
| 738 | *seq_num_end = HTT_RX_IND_FLUSH_SEQ_NUM_END_GET(*msg_word); |
| 739 | } |
| 740 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 741 | int htt_rx_ind_release(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 742 | { |
| 743 | uint32_t *msg_word; |
| 744 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 745 | msg_word = (uint32_t *) qdf_nbuf_data(rx_ind_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 746 | return HTT_RX_IND_REL_VALID_GET(*msg_word); |
| 747 | } |
| 748 | |
| 749 | void |
| 750 | htt_rx_ind_release_seq_num_range(htt_pdev_handle pdev, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 751 | qdf_nbuf_t rx_ind_msg, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 752 | unsigned *seq_num_start, unsigned *seq_num_end) |
| 753 | { |
| 754 | uint32_t *msg_word; |
| 755 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 756 | msg_word = (uint32_t *) qdf_nbuf_data(rx_ind_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 757 | msg_word++; |
| 758 | *seq_num_start = HTT_RX_IND_REL_SEQ_NUM_START_GET(*msg_word); |
| 759 | *seq_num_end = HTT_RX_IND_REL_SEQ_NUM_END_GET(*msg_word); |
| 760 | } |
| 761 | |
| 762 | void |
| 763 | htt_rx_ind_mpdu_range_info(struct htt_pdev_t *pdev, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 764 | qdf_nbuf_t rx_ind_msg, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 765 | int mpdu_range_num, |
| 766 | enum htt_rx_status *status, int *mpdu_count) |
| 767 | { |
| 768 | uint32_t *msg_word; |
| 769 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 770 | msg_word = (uint32_t *) qdf_nbuf_data(rx_ind_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 771 | msg_word += pdev->rx_mpdu_range_offset_words + mpdu_range_num; |
| 772 | *status = HTT_RX_IND_MPDU_STATUS_GET(*msg_word); |
| 773 | *mpdu_count = HTT_RX_IND_MPDU_COUNT_GET(*msg_word); |
| 774 | } |
| 775 | |
| 776 | /** |
| 777 | * htt_rx_ind_rssi_dbm() - Return the RSSI provided in a rx indication message. |
| 778 | * |
| 779 | * @pdev: the HTT instance the rx data was received on |
| 780 | * @rx_ind_msg: the netbuf containing the rx indication message |
| 781 | * |
| 782 | * Return the RSSI from an rx indication message, in dBm units. |
| 783 | * |
| 784 | * Return: RSSI in dBm, or HTT_INVALID_RSSI |
| 785 | */ |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 786 | int16_t htt_rx_ind_rssi_dbm(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 787 | { |
| 788 | int8_t rssi; |
| 789 | uint32_t *msg_word; |
| 790 | |
| 791 | msg_word = (uint32_t *) |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 792 | (qdf_nbuf_data(rx_ind_msg) + |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 793 | HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); |
| 794 | |
| 795 | /* check if the RX_IND message contains valid rx PPDU start info */ |
| 796 | if (!HTT_RX_IND_START_VALID_GET(*msg_word)) |
| 797 | return HTT_RSSI_INVALID; |
| 798 | |
| 799 | rssi = HTT_RX_IND_RSSI_CMB_GET(*msg_word); |
| 800 | return (HTT_TGT_RSSI_INVALID == rssi) ? |
| 801 | HTT_RSSI_INVALID : rssi; |
| 802 | } |
| 803 | |
| 804 | /** |
| 805 | * htt_rx_ind_rssi_dbm_chain() - Return the RSSI for a chain provided in a rx |
| 806 | * indication message. |
| 807 | * @pdev: the HTT instance the rx data was received on |
| 808 | * @rx_ind_msg: the netbuf containing the rx indication message |
| 809 | * @chain: the index of the chain (0-4) |
| 810 | * |
| 811 | * Return the RSSI for a chain from an rx indication message, in dBm units. |
| 812 | * |
| 813 | * Return: RSSI, or HTT_INVALID_RSSI |
| 814 | */ |
| 815 | int16_t |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 816 | htt_rx_ind_rssi_dbm_chain(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 817 | int8_t chain) |
| 818 | { |
| 819 | int8_t rssi; |
| 820 | uint32_t *msg_word; |
| 821 | |
| 822 | if (chain < 0 || chain > 3) |
| 823 | return HTT_RSSI_INVALID; |
| 824 | |
| 825 | msg_word = (uint32_t *) |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 826 | (qdf_nbuf_data(rx_ind_msg) + |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 827 | HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); |
| 828 | |
| 829 | /* check if the RX_IND message contains valid rx PPDU start info */ |
| 830 | if (!HTT_RX_IND_START_VALID_GET(*msg_word)) |
| 831 | return HTT_RSSI_INVALID; |
| 832 | |
| 833 | msg_word += 1 + chain; |
| 834 | |
| 835 | rssi = HTT_RX_IND_RSSI_PRI20_GET(*msg_word); |
| 836 | return (HTT_TGT_RSSI_INVALID == rssi) ? |
| 837 | HTT_RSSI_INVALID : |
| 838 | rssi; |
| 839 | } |
| 840 | |
| 841 | /** |
| 842 | * htt_rx_ind_legacy_rate() - Return the data rate |
| 843 | * @pdev: the HTT instance the rx data was received on |
| 844 | * @rx_ind_msg: the netbuf containing the rx indication message |
| 845 | * @legacy_rate: (output) the data rate |
| 846 | * The legacy_rate parameter's value depends on the |
| 847 | * legacy_rate_sel value. |
| 848 | * If legacy_rate_sel is 0: |
| 849 | * 0x8: OFDM 48 Mbps |
| 850 | * 0x9: OFDM 24 Mbps |
| 851 | * 0xA: OFDM 12 Mbps |
| 852 | * 0xB: OFDM 6 Mbps |
| 853 | * 0xC: OFDM 54 Mbps |
| 854 | * 0xD: OFDM 36 Mbps |
| 855 | * 0xE: OFDM 18 Mbps |
| 856 | * 0xF: OFDM 9 Mbps |
| 857 | * If legacy_rate_sel is 1: |
| 858 | * 0x8: CCK 11 Mbps long preamble |
| 859 | * 0x9: CCK 5.5 Mbps long preamble |
| 860 | * 0xA: CCK 2 Mbps long preamble |
| 861 | * 0xB: CCK 1 Mbps long preamble |
| 862 | * 0xC: CCK 11 Mbps short preamble |
| 863 | * 0xD: CCK 5.5 Mbps short preamble |
| 864 | * 0xE: CCK 2 Mbps short preamble |
| 865 | * -1 on error. |
| 866 | * @legacy_rate_sel: (output) 0 to indicate OFDM, 1 to indicate CCK. |
| 867 | * -1 on error. |
| 868 | * |
| 869 | * Return the data rate provided in a rx indication message. |
| 870 | */ |
| 871 | void |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 872 | htt_rx_ind_legacy_rate(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 873 | uint8_t *legacy_rate, uint8_t *legacy_rate_sel) |
| 874 | { |
| 875 | uint32_t *msg_word; |
| 876 | |
| 877 | msg_word = (uint32_t *) |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 878 | (qdf_nbuf_data(rx_ind_msg) + |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 879 | HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); |
| 880 | |
| 881 | /* check if the RX_IND message contains valid rx PPDU start info */ |
| 882 | if (!HTT_RX_IND_START_VALID_GET(*msg_word)) { |
| 883 | *legacy_rate = -1; |
| 884 | *legacy_rate_sel = -1; |
| 885 | return; |
| 886 | } |
| 887 | |
| 888 | *legacy_rate = HTT_RX_IND_LEGACY_RATE_GET(*msg_word); |
| 889 | *legacy_rate_sel = HTT_RX_IND_LEGACY_RATE_SEL_GET(*msg_word); |
| 890 | } |
| 891 | |
| 892 | /** |
| 893 | * htt_rx_ind_timestamp() - Return the timestamp |
| 894 | * @pdev: the HTT instance the rx data was received on |
| 895 | * @rx_ind_msg: the netbuf containing the rx indication message |
| 896 | * @timestamp_microsec: (output) the timestamp to microsecond resolution. |
| 897 | * -1 on error. |
| 898 | * @timestamp_submicrosec: the submicrosecond portion of the |
| 899 | * timestamp. -1 on error. |
| 900 | * |
| 901 | * Return the timestamp provided in a rx indication message. |
| 902 | */ |
| 903 | void |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 904 | htt_rx_ind_timestamp(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 905 | uint32_t *timestamp_microsec, |
| 906 | uint8_t *timestamp_submicrosec) |
| 907 | { |
| 908 | uint32_t *msg_word; |
| 909 | |
| 910 | msg_word = (uint32_t *) |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 911 | (qdf_nbuf_data(rx_ind_msg) + |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 912 | HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); |
| 913 | |
| 914 | /* check if the RX_IND message contains valid rx PPDU start info */ |
| 915 | if (!HTT_RX_IND_END_VALID_GET(*msg_word)) { |
| 916 | *timestamp_microsec = -1; |
| 917 | *timestamp_submicrosec = -1; |
| 918 | return; |
| 919 | } |
| 920 | |
| 921 | *timestamp_microsec = *(msg_word + 6); |
| 922 | *timestamp_submicrosec = |
| 923 | HTT_RX_IND_TIMESTAMP_SUBMICROSEC_GET(*msg_word); |
| 924 | } |
| 925 | |
| 926 | #define INVALID_TSF -1 |
| 927 | /** |
| 928 | * htt_rx_ind_tsf32() - Return the TSF timestamp |
| 929 | * @pdev: the HTT instance the rx data was received on |
| 930 | * @rx_ind_msg: the netbuf containing the rx indication message |
| 931 | * |
| 932 | * Return the TSF timestamp provided in a rx indication message. |
| 933 | * |
| 934 | * Return: TSF timestamp |
| 935 | */ |
| 936 | uint32_t |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 937 | htt_rx_ind_tsf32(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 938 | { |
| 939 | uint32_t *msg_word; |
| 940 | |
| 941 | msg_word = (uint32_t *) |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 942 | (qdf_nbuf_data(rx_ind_msg) + |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 943 | HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET); |
| 944 | |
| 945 | /* check if the RX_IND message contains valid rx PPDU start info */ |
| 946 | if (!HTT_RX_IND_END_VALID_GET(*msg_word)) |
| 947 | return INVALID_TSF; |
| 948 | |
| 949 | return *(msg_word + 5); |
| 950 | } |
| 951 | |
| 952 | /** |
| 953 | * htt_rx_ind_ext_tid() - Return the extended traffic ID provided in a rx indication message. |
| 954 | * @pdev: the HTT instance the rx data was received on |
| 955 | * @rx_ind_msg: the netbuf containing the rx indication message |
| 956 | * |
| 957 | * Return the extended traffic ID in a rx indication message. |
| 958 | * |
| 959 | * Return: Extended TID |
| 960 | */ |
| 961 | uint8_t |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 962 | htt_rx_ind_ext_tid(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 963 | { |
| 964 | uint32_t *msg_word; |
| 965 | |
| 966 | msg_word = (uint32_t *) |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 967 | (qdf_nbuf_data(rx_ind_msg)); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 968 | |
| 969 | return HTT_RX_IND_EXT_TID_GET(*msg_word); |
| 970 | } |
| 971 | |
| 972 | /*--- stats confirmation message ---*/ |
| 973 | |
| 974 | void |
| 975 | htt_t2h_dbg_stats_hdr_parse(uint8_t *stats_info_list, |
| 976 | enum htt_dbg_stats_type *type, |
| 977 | enum htt_dbg_stats_status *status, |
| 978 | int *length, uint8_t **stats_data) |
| 979 | { |
| 980 | uint32_t *msg_word = (uint32_t *) stats_info_list; |
| 981 | *type = HTT_T2H_STATS_CONF_TLV_TYPE_GET(*msg_word); |
| 982 | *status = HTT_T2H_STATS_CONF_TLV_STATUS_GET(*msg_word); |
| 983 | *length = HTT_T2H_STATS_CONF_TLV_HDR_SIZE + /* header length */ |
| 984 | HTT_T2H_STATS_CONF_TLV_LENGTH_GET(*msg_word); /* data len */ |
| 985 | *stats_data = stats_info_list + HTT_T2H_STATS_CONF_TLV_HDR_SIZE; |
| 986 | } |
| 987 | |
| 988 | void |
| 989 | htt_rx_frag_ind_flush_seq_num_range(htt_pdev_handle pdev, |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 990 | qdf_nbuf_t rx_frag_ind_msg, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 991 | int *seq_num_start, int *seq_num_end) |
| 992 | { |
| 993 | uint32_t *msg_word; |
| 994 | |
Nirav Shah | cbc6d72 | 2016-03-01 16:24:53 +0530 | [diff] [blame^] | 995 | msg_word = (uint32_t *) qdf_nbuf_data(rx_frag_ind_msg); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 996 | msg_word++; |
| 997 | *seq_num_start = HTT_RX_FRAG_IND_FLUSH_SEQ_NUM_START_GET(*msg_word); |
| 998 | *seq_num_end = HTT_RX_FRAG_IND_FLUSH_SEQ_NUM_END_GET(*msg_word); |
| 999 | } |