1 /* 2 * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <qdf_mem.h> /* qdf_mem_malloc,free, etc. */ 20 #include <qdf_types.h> /* qdf_print, bool */ 21 #include <qdf_nbuf.h> /* qdf_nbuf_t, etc. */ 22 #include <qdf_timer.h> /* qdf_timer_free */ 23 24 #include <htt.h> /* HTT_HL_RX_DESC_SIZE */ 25 #include <ol_cfg.h> 26 #include <ol_rx.h> 27 #include <ol_htt_rx_api.h> 28 #include <htt_internal.h> /* HTT_ASSERT, htt_pdev_t, HTT_RX_BUF_SIZE */ 29 #include "regtable.h" 30 31 #include <cds_ieee80211_common.h> /* ieee80211_frame, ieee80211_qoscntl */ 32 #include <cds_utils.h> 33 #include <wlan_policy_mgr_api.h> 34 #include "ol_txrx_types.h" 35 36 /* 37 * This function is used both below within this file (which the compiler 38 * will hopefully inline), and out-line from other files via the 39 * htt_rx_msdu_first_msdu_flag function pointer. 40 */ 41 static inline bool 42 htt_rx_msdu_first_msdu_flag_hl(htt_pdev_handle pdev, void *msdu_desc) 43 { 44 return ((u_int8_t *)msdu_desc - sizeof(struct hl_htt_rx_ind_base)) 45 [HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_FLAG_OFFSET)] & 46 HTT_RX_IND_HL_FLAG_FIRST_MSDU ? true : false; 47 } 48 49 u_int16_t 50 htt_rx_msdu_rx_desc_size_hl( 51 htt_pdev_handle pdev, 52 void *msdu_desc 53 ) 54 { 55 return ((u_int8_t *)(msdu_desc) - HTT_RX_IND_HL_BYTES) 56 [HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)]; 57 } 58 59 #ifdef CHECKSUM_OFFLOAD 60 static void 61 htt_set_checksum_result_hl(qdf_nbuf_t msdu, 62 struct htt_host_rx_desc_base *rx_desc) 63 { 64 u_int8_t flag = ((u_int8_t *)rx_desc - 65 sizeof(struct hl_htt_rx_ind_base))[ 66 HTT_ENDIAN_BYTE_IDX_SWAP( 67 HTT_RX_IND_HL_FLAG_OFFSET)]; 68 69 int is_ipv6 = flag & HTT_RX_IND_HL_FLAG_IPV6 ? 1 : 0; 70 int is_tcp = flag & HTT_RX_IND_HL_FLAG_TCP ? 1 : 0; 71 int is_udp = flag & HTT_RX_IND_HL_FLAG_UDP ? 1 : 0; 72 73 qdf_nbuf_rx_cksum_t cksum = { 74 QDF_NBUF_RX_CKSUM_NONE, 75 QDF_NBUF_RX_CKSUM_NONE, 76 0 77 }; 78 79 switch ((is_udp << 2) | (is_tcp << 1) | (is_ipv6 << 0)) { 80 case 0x4: 81 cksum.l4_type = QDF_NBUF_RX_CKSUM_UDP; 82 break; 83 case 0x2: 84 cksum.l4_type = QDF_NBUF_RX_CKSUM_TCP; 85 break; 86 case 0x5: 87 cksum.l4_type = QDF_NBUF_RX_CKSUM_UDPIPV6; 88 break; 89 case 0x3: 90 cksum.l4_type = QDF_NBUF_RX_CKSUM_TCPIPV6; 91 break; 92 default: 93 cksum.l4_type = QDF_NBUF_RX_CKSUM_NONE; 94 break; 95 } 96 if (cksum.l4_type != (qdf_nbuf_l4_rx_cksum_type_t) 97 QDF_NBUF_RX_CKSUM_NONE) { 98 cksum.l4_result = flag & HTT_RX_IND_HL_FLAG_C4_FAILED ? 99 QDF_NBUF_RX_CKSUM_NONE : 100 QDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY; 101 } 102 qdf_nbuf_set_rx_cksum(msdu, &cksum); 103 } 104 #else 105 static inline 106 void htt_set_checksum_result_hl(qdf_nbuf_t msdu, 107 struct htt_host_rx_desc_base *rx_desc) 108 { 109 } 110 #endif 111 112 /** 113 * htt_rx_fill_ring_count() - replenish rx msdu buffer 114 * @pdev: Handle (pointer) to HTT pdev. 115 * 116 * This funciton will replenish the rx buffer to the max number 117 * that can be kept in the ring 118 * 119 * Return: None 120 */ 121 void htt_rx_fill_ring_count(htt_pdev_handle pdev) 122 { 123 } 124 125 /** 126 * htt_rx_mpdu_desc_list_next_hl() - provides an abstract way to obtain 127 * the next MPDU descriptor 128 * @pdev: the HTT instance the rx data was received on 129 * @rx_ind_msg: the netbuf containing the rx indication message 130 * 131 * for HL, the returned value is not mpdu_desc, 132 * it's translated hl_rx_desc just after the hl_ind_msg 133 * for HL AMSDU, we can't point to payload now, because 134 * hl rx desc is not fixed, we can't retrieve the desc 135 * by minus rx_desc_size when release. keep point to hl rx desc 136 * now 137 * 138 * Return: next abstract rx descriptor from the series of MPDUs 139 * referenced by an rx ind msg 140 */ 141 static inline void * 142 htt_rx_mpdu_desc_list_next_hl(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg) 143 { 144 void *mpdu_desc = (void *)qdf_nbuf_data(rx_ind_msg); 145 return mpdu_desc; 146 } 147 148 /** 149 * htt_rx_msdu_desc_retrieve_hl() - Retrieve a previously-stored rx descriptor 150 * from a MSDU buffer 151 * @pdev: the HTT instance the rx data was received on 152 * @msdu - the buffer containing the MSDU payload 153 * 154 * currently for HL AMSDU, we don't point to payload. 155 * we shift to payload in ol_rx_deliver later 156 * 157 * Return: the corresponding abstract rx MSDU descriptor 158 */ 159 static inline void * 160 htt_rx_msdu_desc_retrieve_hl(htt_pdev_handle pdev, qdf_nbuf_t msdu) 161 { 162 return qdf_nbuf_data(msdu); 163 } 164 165 static 166 bool htt_rx_mpdu_is_encrypted_hl(htt_pdev_handle pdev, void *mpdu_desc) 167 { 168 if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == true) { 169 /* Fix Me: only for little endian */ 170 struct hl_htt_rx_desc_base *rx_desc = 171 (struct hl_htt_rx_desc_base *)mpdu_desc; 172 173 return HTT_WORD_GET(*(u_int32_t *)rx_desc, 174 HTT_HL_RX_DESC_MPDU_ENC); 175 } else { 176 /* not first msdu, no encrypt info for hl */ 177 qdf_print( 178 "Error: get encrypted from a not-first msdu.\n"); 179 qdf_assert(0); 180 return false; 181 } 182 } 183 184 static inline bool 185 htt_rx_msdu_chan_info_present_hl(htt_pdev_handle pdev, void *mpdu_desc) 186 { 187 if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == true && 188 HTT_WORD_GET(*(u_int32_t *)mpdu_desc, 189 HTT_HL_RX_DESC_CHAN_INFO_PRESENT)) 190 return true; 191 192 return false; 193 } 194 195 static bool 196 htt_rx_msdu_center_freq_hl(htt_pdev_handle pdev, 197 struct ol_txrx_peer_t *peer, 198 void *mpdu_desc, 199 uint16_t *primary_chan_center_freq_mhz, 200 uint16_t *contig_chan1_center_freq_mhz, 201 uint16_t *contig_chan2_center_freq_mhz, 202 uint8_t *phy_mode) 203 { 204 int pn_len, index; 205 uint32_t *chan_info; 206 207 index = htt_rx_msdu_is_wlan_mcast(pdev, mpdu_desc) ? 208 txrx_sec_mcast : txrx_sec_ucast; 209 210 pn_len = (peer ? 211 pdev->txrx_pdev->rx_pn[peer->security[index].sec_type]. 212 len : 0); 213 chan_info = (uint32_t *)((uint8_t *)mpdu_desc + 214 HTT_HL_RX_DESC_PN_OFFSET + pn_len); 215 216 if (htt_rx_msdu_chan_info_present_hl(pdev, mpdu_desc)) { 217 if (primary_chan_center_freq_mhz) 218 *primary_chan_center_freq_mhz = 219 HTT_WORD_GET( 220 *chan_info, 221 HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ); 222 if (contig_chan1_center_freq_mhz) 223 *contig_chan1_center_freq_mhz = 224 HTT_WORD_GET( 225 *chan_info, 226 HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ); 227 chan_info++; 228 if (contig_chan2_center_freq_mhz) 229 *contig_chan2_center_freq_mhz = 230 HTT_WORD_GET( 231 *chan_info, 232 HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ); 233 if (phy_mode) 234 *phy_mode = 235 HTT_WORD_GET(*chan_info, 236 HTT_CHAN_INFO_PHY_MODE); 237 return true; 238 } 239 240 if (primary_chan_center_freq_mhz) 241 *primary_chan_center_freq_mhz = 0; 242 if (contig_chan1_center_freq_mhz) 243 *contig_chan1_center_freq_mhz = 0; 244 if (contig_chan2_center_freq_mhz) 245 *contig_chan2_center_freq_mhz = 0; 246 if (phy_mode) 247 *phy_mode = 0; 248 return false; 249 } 250 251 static bool 252 htt_rx_msdu_desc_key_id_hl(htt_pdev_handle htt_pdev, 253 void *mpdu_desc, u_int8_t *key_id) 254 { 255 if (htt_rx_msdu_first_msdu_flag_hl(htt_pdev, mpdu_desc) == true) { 256 /* Fix Me: only for little endian */ 257 struct hl_htt_rx_desc_base *rx_desc = 258 (struct hl_htt_rx_desc_base *)mpdu_desc; 259 260 *key_id = rx_desc->key_id_oct; 261 return true; 262 } 263 264 return false; 265 } 266 267 /** 268 * htt_rx_mpdu_desc_retry_hl() - Returns the retry bit from the Rx descriptor 269 * for the High Latency driver 270 * @pdev: Handle (pointer) to HTT pdev. 271 * @mpdu_desc: Void pointer to the Rx descriptor for MPDU 272 * before the beginning of the payload. 273 * 274 * This function returns the retry bit of the 802.11 header for the 275 * provided rx MPDU descriptor. For the high latency driver, this function 276 * pretends as if the retry bit is never set so that the mcast duplicate 277 * detection never fails. 278 * 279 * Return: boolean -- false always for HL 280 */ 281 static inline bool 282 htt_rx_mpdu_desc_retry_hl(htt_pdev_handle pdev, void *mpdu_desc) 283 { 284 return false; 285 } 286 287 static int 288 htt_rx_amsdu_pop_hl( 289 htt_pdev_handle pdev, 290 qdf_nbuf_t rx_ind_msg, 291 qdf_nbuf_t *head_msdu, 292 qdf_nbuf_t *tail_msdu, 293 uint32_t *msdu_count) 294 { 295 pdev->rx_desc_size_hl = 296 (qdf_nbuf_data(rx_ind_msg)) 297 [HTT_ENDIAN_BYTE_IDX_SWAP( 298 HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)]; 299 300 /* point to the rx desc */ 301 qdf_nbuf_pull_head(rx_ind_msg, 302 sizeof(struct hl_htt_rx_ind_base)); 303 *head_msdu = *tail_msdu = rx_ind_msg; 304 305 htt_set_checksum_result_hl(rx_ind_msg, 306 (struct htt_host_rx_desc_base *) 307 (qdf_nbuf_data(rx_ind_msg))); 308 309 qdf_nbuf_set_next(*tail_msdu, NULL); 310 return 0; 311 } 312 313 static int 314 htt_rx_frag_pop_hl( 315 htt_pdev_handle pdev, 316 qdf_nbuf_t frag_msg, 317 qdf_nbuf_t *head_msdu, 318 qdf_nbuf_t *tail_msdu, 319 uint32_t *msdu_count) 320 { 321 qdf_nbuf_pull_head(frag_msg, HTT_RX_FRAG_IND_BYTES); 322 pdev->rx_desc_size_hl = 323 (qdf_nbuf_data(frag_msg)) 324 [HTT_ENDIAN_BYTE_IDX_SWAP( 325 HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)]; 326 327 /* point to the rx desc */ 328 qdf_nbuf_pull_head(frag_msg, 329 sizeof(struct hl_htt_rx_ind_base)); 330 *head_msdu = *tail_msdu = frag_msg; 331 332 qdf_nbuf_set_next(*tail_msdu, NULL); 333 return 1; 334 } 335 336 static inline int 337 htt_rx_offload_msdu_cnt_hl(htt_pdev_handle pdev) 338 { 339 return 1; 340 } 341 342 static inline int 343 htt_rx_offload_msdu_pop_hl(htt_pdev_handle pdev, 344 qdf_nbuf_t offload_deliver_msg, 345 int *vdev_id, 346 int *peer_id, 347 int *tid, 348 u_int8_t *fw_desc, 349 qdf_nbuf_t *head_buf, 350 qdf_nbuf_t *tail_buf) 351 { 352 qdf_nbuf_t buf; 353 u_int32_t *msdu_hdr, msdu_len; 354 int ret = 0; 355 356 *head_buf = *tail_buf = buf = offload_deliver_msg; 357 msdu_hdr = (u_int32_t *)qdf_nbuf_data(buf); 358 /* First dword */ 359 360 /* Second dword */ 361 msdu_hdr++; 362 msdu_len = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_GET(*msdu_hdr); 363 *peer_id = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_GET(*msdu_hdr); 364 365 /* Third dword */ 366 msdu_hdr++; 367 *vdev_id = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_GET(*msdu_hdr); 368 *tid = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_GET(*msdu_hdr); 369 *fw_desc = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_GET(*msdu_hdr); 370 371 qdf_nbuf_pull_head(buf, HTT_RX_OFFLOAD_DELIVER_IND_MSDU_HDR_BYTES 372 + HTT_RX_OFFLOAD_DELIVER_IND_HDR_BYTES); 373 374 if (msdu_len <= qdf_nbuf_len(buf)) { 375 qdf_nbuf_set_pktlen(buf, msdu_len); 376 } else { 377 QDF_TRACE(QDF_MODULE_ID_HTT, QDF_TRACE_LEVEL_ERROR, 378 "%s: drop frame with invalid msdu len %d %d", 379 __func__, msdu_len, (int)qdf_nbuf_len(buf)); 380 qdf_nbuf_free(offload_deliver_msg); 381 ret = -1; 382 } 383 384 return ret; 385 } 386 387 static uint16_t 388 htt_rx_mpdu_desc_seq_num_hl(htt_pdev_handle pdev, void *mpdu_desc) 389 { 390 if (pdev->rx_desc_size_hl) { 391 return pdev->cur_seq_num_hl = 392 (u_int16_t)(HTT_WORD_GET(*(u_int32_t *)mpdu_desc, 393 HTT_HL_RX_DESC_MPDU_SEQ_NUM)); 394 } else { 395 return (u_int16_t)(pdev->cur_seq_num_hl); 396 } 397 } 398 399 static void 400 htt_rx_mpdu_desc_pn_hl( 401 htt_pdev_handle pdev, 402 void *mpdu_desc, 403 union htt_rx_pn_t *pn, 404 int pn_len_bits) 405 { 406 if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == true) { 407 /* Fix Me: only for little endian */ 408 struct hl_htt_rx_desc_base *rx_desc = 409 (struct hl_htt_rx_desc_base *)mpdu_desc; 410 u_int32_t *word_ptr = (u_int32_t *)pn->pn128; 411 412 /* TODO: for Host of big endian */ 413 switch (pn_len_bits) { 414 case 128: 415 /* bits 128:64 */ 416 *(word_ptr + 3) = rx_desc->pn_127_96; 417 /* bits 63:0 */ 418 *(word_ptr + 2) = rx_desc->pn_95_64; 419 case 48: 420 /* bits 48:0 421 * copy 64 bits 422 */ 423 *(word_ptr + 1) = rx_desc->u0.pn_63_32; 424 case 24: 425 /* bits 23:0 426 * copy 32 bits 427 */ 428 *(word_ptr + 0) = rx_desc->pn_31_0; 429 break; 430 default: 431 QDF_TRACE(QDF_MODULE_ID_HTT, QDF_TRACE_LEVEL_ERROR, 432 "Error: invalid length spec (%d bits) for PN", 433 pn_len_bits); 434 qdf_assert(0); 435 break; 436 }; 437 } else { 438 /* not first msdu, no pn info */ 439 QDF_TRACE(QDF_MODULE_ID_HTT, QDF_TRACE_LEVEL_ERROR, 440 "Error: get pn from a not-first msdu."); 441 qdf_assert(0); 442 } 443 } 444 445 /** 446 * htt_rx_mpdu_desc_tid_hl() - Returns the TID value from the Rx descriptor 447 * for High Latency driver 448 * @pdev: Handle (pointer) to HTT pdev. 449 * @mpdu_desc: Void pointer to the Rx descriptor for the MPDU 450 * before the beginning of the payload. 451 * 452 * This function returns the TID set in the 802.11 QoS Control for the MPDU 453 * in the packet header, by looking at the mpdu_start of the Rx descriptor. 454 * Rx descriptor gets a copy of the TID from the MAC. 455 * For the HL driver, this is currently uimplemented and always returns 456 * an invalid tid. It is the responsibility of the caller to make 457 * sure that return value is checked for valid range. 458 * 459 * Return: Invalid TID value (0xff) for HL driver. 460 */ 461 static inline uint8_t 462 htt_rx_mpdu_desc_tid_hl(htt_pdev_handle pdev, void *mpdu_desc) 463 { 464 return 0xff; /* Invalid TID */ 465 } 466 467 static inline bool 468 htt_rx_msdu_desc_completes_mpdu_hl(htt_pdev_handle pdev, void *msdu_desc) 469 { 470 return ( 471 ((u_int8_t *)(msdu_desc) - sizeof(struct hl_htt_rx_ind_base)) 472 [HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_FLAG_OFFSET)] 473 & HTT_RX_IND_HL_FLAG_LAST_MSDU) 474 ? true : false; 475 } 476 477 static inline int 478 htt_rx_msdu_has_wlan_mcast_flag_hl(htt_pdev_handle pdev, void *msdu_desc) 479 { 480 /* currently, only first msdu has hl rx_desc */ 481 return htt_rx_msdu_first_msdu_flag_hl(pdev, msdu_desc) == true; 482 } 483 484 static inline bool 485 htt_rx_msdu_is_wlan_mcast_hl(htt_pdev_handle pdev, void *msdu_desc) 486 { 487 struct hl_htt_rx_desc_base *rx_desc = 488 (struct hl_htt_rx_desc_base *)msdu_desc; 489 490 return 491 HTT_WORD_GET(*(u_int32_t *)rx_desc, HTT_HL_RX_DESC_MCAST_BCAST); 492 } 493 494 static inline int 495 htt_rx_msdu_is_frag_hl(htt_pdev_handle pdev, void *msdu_desc) 496 { 497 struct hl_htt_rx_desc_base *rx_desc = 498 (struct hl_htt_rx_desc_base *)msdu_desc; 499 500 return 501 HTT_WORD_GET(*(u_int32_t *)rx_desc, HTT_HL_RX_DESC_MCAST_BCAST); 502 } 503 504 int htt_rx_attach(struct htt_pdev_t *pdev) 505 { 506 pdev->rx_ring.size = HTT_RX_RING_SIZE_MIN; 507 HTT_ASSERT2(IS_PWR2(pdev->rx_ring.size)); 508 pdev->rx_ring.size_mask = pdev->rx_ring.size - 1; 509 /* host can force ring base address if it wish to do so */ 510 pdev->rx_ring.base_paddr = 0; 511 htt_rx_amsdu_pop = htt_rx_amsdu_pop_hl; 512 htt_rx_frag_pop = htt_rx_frag_pop_hl; 513 htt_rx_offload_msdu_cnt = htt_rx_offload_msdu_cnt_hl; 514 htt_rx_offload_msdu_pop = htt_rx_offload_msdu_pop_hl; 515 htt_rx_mpdu_desc_list_next = htt_rx_mpdu_desc_list_next_hl; 516 htt_rx_mpdu_desc_retry = htt_rx_mpdu_desc_retry_hl; 517 htt_rx_mpdu_desc_seq_num = htt_rx_mpdu_desc_seq_num_hl; 518 htt_rx_mpdu_desc_pn = htt_rx_mpdu_desc_pn_hl; 519 htt_rx_mpdu_desc_tid = htt_rx_mpdu_desc_tid_hl; 520 htt_rx_msdu_desc_completes_mpdu = htt_rx_msdu_desc_completes_mpdu_hl; 521 htt_rx_msdu_first_msdu_flag = htt_rx_msdu_first_msdu_flag_hl; 522 htt_rx_msdu_has_wlan_mcast_flag = htt_rx_msdu_has_wlan_mcast_flag_hl; 523 htt_rx_msdu_is_wlan_mcast = htt_rx_msdu_is_wlan_mcast_hl; 524 htt_rx_msdu_is_frag = htt_rx_msdu_is_frag_hl; 525 htt_rx_msdu_desc_retrieve = htt_rx_msdu_desc_retrieve_hl; 526 htt_rx_mpdu_is_encrypted = htt_rx_mpdu_is_encrypted_hl; 527 htt_rx_msdu_desc_key_id = htt_rx_msdu_desc_key_id_hl; 528 htt_rx_msdu_chan_info_present = htt_rx_msdu_chan_info_present_hl; 529 htt_rx_msdu_center_freq = htt_rx_msdu_center_freq_hl; 530 531 /* 532 * HL case, the rx descriptor can be different sizes for 533 * different sub-types of RX_IND messages, e.g. for the 534 * initial vs. interior vs. final MSDUs within a PPDU. 535 * The size of each RX_IND message's rx desc is read from 536 * a field within the RX_IND message itself. 537 * In the meantime, until the rx_desc_size_hl variable is 538 * set to its real value based on the RX_IND message, 539 * initialize it to a reasonable value (zero). 540 */ 541 pdev->rx_desc_size_hl = 0; 542 return 0; /* success */ 543 } 544