1 /* 2 * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. 3 * 4 * 5 * 6 * Permission to use, copy, modify, and/or distribute this software for 7 * any purpose with or without fee is hereby granted, provided that the 8 * above copyright notice and this permission notice appear in all 9 * copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 12 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 14 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 15 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 16 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 17 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 18 * PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 22 #define ATH_MODULE_NAME hif 23 #include <qdf_types.h> 24 #include <qdf_status.h> 25 #include <qdf_timer.h> 26 #include <qdf_time.h> 27 #include <qdf_lock.h> 28 #include <qdf_mem.h> 29 #include <qdf_util.h> 30 #include <qdf_defer.h> 31 #include <qdf_atomic.h> 32 #include <qdf_nbuf.h> 33 #include <athdefs.h> 34 #include <qdf_net_types.h> 35 #include <a_types.h> 36 #include <athdefs.h> 37 #include <a_osapi.h> 38 #include <hif.h> 39 #include <htc_services.h> 40 #include <a_debug.h> 41 #include <htc_internal.h> 42 #include "hif_sdio_internal.h" 43 #include "transfer.h" 44 45 /** 46 * hif_dev_rw_completion_handler() - Completion routine 47 * for ALL HIF layer async I/O 48 * @context: hif send context 49 * @status: completion routine sync/async context 50 * 51 * Return: 0 for success and non-zero for failure 52 */ 53 54 QDF_STATUS hif_dev_rw_completion_handler(void *ctx, QDF_STATUS status) 55 { 56 QDF_STATUS (*txCompHandler)(void *, qdf_nbuf_t, uint32_t, uint32_t); 57 struct hif_sendContext *sctx = (struct hif_sendContext *)ctx; 58 struct hif_sdio_device *pdev = sctx->pDev; 59 unsigned int xfer_id = sctx->transferID; 60 uint32_t toeplitz_hash_result = 0; 61 qdf_nbuf_t buf = sctx->netbuf; 62 63 if (sctx->bNewAlloc) 64 qdf_mem_free(ctx); 65 else 66 qdf_nbuf_pull_head(buf, sctx->head_data_len); 67 68 txCompHandler = pdev->hif_callbacks.txCompletionHandler; 69 if (txCompHandler) { 70 txCompHandler(pdev->hif_callbacks.Context, buf, 71 xfer_id, toeplitz_hash_result); 72 } 73 74 return QDF_STATUS_SUCCESS; 75 } 76 77 /** 78 * hif_dev_send_buffer() - send buffer to sdio device 79 * @pDev: HIf device object 80 * @xfer_id: transfer id 81 * @pipe: ul/dl pipe 82 * @nbytes: no of bytes to transfer 83 * @buf: pointer to buffer 84 * 85 * Return: 0 for success and non-zero for failure 86 */ 87 QDF_STATUS hif_dev_send_buffer(struct hif_sdio_device *pdev, uint32_t xfer_id, 88 uint8_t pipe, uint32_t nbytes, qdf_nbuf_t buf) 89 { 90 QDF_STATUS status; 91 unsigned char *pData; 92 struct hif_sendContext *sctx; 93 uint32_t request = hif_get_send_buffer_flags(pdev); 94 uint32_t padded_length; 95 unsigned long addr = 0; 96 int frag_count = 0, i, count, head_len; 97 98 if (hif_get_send_address(pdev, pipe, &addr)) { 99 hif_err("%s: Invalid address map for pipe 0x%x", 100 __func__, pipe); 101 102 return QDF_STATUS_E_INVAL; 103 } 104 105 padded_length = DEV_CALC_SEND_PADDED_LEN(pdev, nbytes); 106 A_ASSERT(padded_length - nbytes < HIF_DUMMY_SPACE_MASK + 1); 107 108 request |= ((padded_length - nbytes) << 16); 109 110 frag_count = qdf_nbuf_get_num_frags(buf); 111 112 if (frag_count > 1) { 113 /* Header data length should be total sending length. 114 * Subtract internal data length of netbuf 115 */ 116 head_len = sizeof(struct hif_sendContext) + 117 (nbytes - qdf_nbuf_get_frag_len(buf, frag_count - 1)); 118 } else { 119 /* 120 * | hif_sendContext | netbuf->data 121 */ 122 head_len = sizeof(struct hif_sendContext); 123 } 124 125 /* Check whether head room is enough to save extra head data */ 126 if ((head_len <= qdf_nbuf_headroom(buf)) && 127 (qdf_nbuf_tailroom(buf) >= (padded_length - nbytes))) { 128 sctx = (struct hif_sendContext *)qdf_nbuf_push_head(buf, 129 head_len); 130 sctx->bNewAlloc = false; 131 } else { 132 sctx = (struct hif_sendContext *)qdf_mem_malloc(sizeof(*sctx) + 133 padded_length); 134 if (sctx) 135 sctx->bNewAlloc = true; 136 else 137 return QDF_STATUS_E_NOMEM; 138 } 139 140 sctx->netbuf = buf; 141 sctx->pDev = pdev; 142 sctx->transferID = xfer_id; 143 sctx->head_data_len = head_len; 144 /* 145 * Copy data to head part of netbuf or head of allocated buffer. 146 * if buffer is new allocated, the last buffer should be copied also. 147 * It assume last fragment is internal buffer of netbuf 148 * sometime total length of fragments larger than nbytes 149 */ 150 pData = (unsigned char *)sctx + sizeof(struct hif_sendContext); 151 for (i = 0, count = sctx->bNewAlloc ? frag_count : frag_count - 1; 152 i < count; 153 i++) { 154 int frag_len = qdf_nbuf_get_frag_len(buf, i); 155 unsigned char *frag_addr = qdf_nbuf_get_frag_vaddr(buf, i); 156 157 if (frag_len > nbytes) 158 frag_len = nbytes; 159 memcpy(pData, frag_addr, frag_len); 160 pData += frag_len; 161 nbytes -= frag_len; 162 if (nbytes <= 0) 163 break; 164 } 165 166 /* Reset pData pointer and sctx out */ 167 pData = (unsigned char *)sctx + sizeof(struct hif_sendContext); 168 169 status = hif_read_write(pdev->HIFDevice, addr, (char *)pData, 170 padded_length, request, (void *)sctx); 171 172 if (status == QDF_STATUS_E_PENDING) { 173 /* 174 * it will return QDF_STATUS_E_PENDING in native HIF 175 * implementation, which should be treated as successful 176 * result here. 177 */ 178 status = QDF_STATUS_SUCCESS; 179 } 180 181 /* release buffer or move back data pointer when failed */ 182 if (status != QDF_STATUS_SUCCESS) { 183 if (sctx->bNewAlloc) 184 qdf_mem_free(sctx); 185 else 186 qdf_nbuf_pull_head(buf, head_len); 187 } 188 189 return status; 190 } 191 192 /** 193 * hif_dev_alloc_and_prepare_rx_packets() - Allocate packets for recv frames. 194 * @pdev : HIF device object 195 * @look_aheads : Look ahead information on the frames 196 * @messages : Number of messages 197 * @queue : Queue to put the allocated frames 198 * 199 * Return : QDF_STATUS_SUCCESS on success else error value 200 */ 201 QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev, 202 uint32_t look_aheads[], 203 int messages, 204 HTC_PACKET_QUEUE *queue) 205 { 206 int i, j; 207 bool no_recycle; 208 int num_messages; 209 HTC_PACKET *packet; 210 HTC_FRAME_HDR *hdr; 211 uint32_t full_length; 212 QDF_STATUS status = QDF_STATUS_SUCCESS; 213 214 /* lock RX while we assemble the packet buffers */ 215 LOCK_HIF_DEV_RX(pdev); 216 217 for (i = 0; i < messages; i++) { 218 hdr = (HTC_FRAME_HDR *)&look_aheads[i]; 219 if (hdr->EndpointID >= ENDPOINT_MAX) { 220 hif_err("%s: Invalid Endpoint:%d\n", 221 __func__, hdr->EndpointID); 222 status = QDF_STATUS_E_INVAL; 223 break; 224 } 225 226 if (hdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) { 227 hif_err("%s: Payload length %d exceeds max HTC : %u", 228 __func__, 229 hdr->PayloadLen, 230 (uint32_t)HTC_MAX_PAYLOAD_LENGTH); 231 status = QDF_STATUS_E_INVAL; 232 break; 233 } 234 235 if ((hdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) { 236 /* HTC header only indicates 1 message to fetch */ 237 num_messages = 1; 238 } else { 239 /* HTC header indicates that every packet to follow 240 * has the same padded length so that it can 241 * be optimally fetched as a full bundle 242 */ 243 num_messages = GET_RECV_BUNDLE_COUNT(hdr->Flags); 244 /* the count doesn't include the starter frame, just 245 * a count of frames to follow 246 */ 247 num_messages++; 248 249 hif_info("%s: HTC header : %u messages in bundle", 250 __func__, num_messages); 251 } 252 253 full_length = DEV_CALC_RECV_PADDED_LEN(pdev, 254 hdr->PayloadLen + 255 sizeof(HTC_FRAME_HDR)); 256 257 /* get packet buffers for each message, if there was a 258 * bundle detected in the header, 259 * use pHdr as a template to fetch all packets in the bundle 260 */ 261 for (j = 0; j < num_messages; j++) { 262 /* reset flag, any packets allocated using the 263 * RecvAlloc() API cannot be recycled on cleanup, 264 * they must be explicitly returned 265 */ 266 no_recycle = false; 267 packet = hif_dev_alloc_rx_buffer(pdev); 268 269 if (!packet) { 270 /* No error, simply need to mark that 271 * we are waiting for buffers. 272 */ 273 pdev->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS; 274 /* pDev->EpWaitingForBuffers = pEndpoint->Id; */ 275 status = QDF_STATUS_E_RESOURCES; 276 break; 277 } 278 /* clear flags */ 279 packet->PktInfo.AsRx.HTCRxFlags = 0; 280 packet->PktInfo.AsRx.IndicationFlags = 0; 281 packet->Status = QDF_STATUS_SUCCESS; 282 283 if (no_recycle) { 284 /* flag that these packets cannot be recycled, 285 * they have to be returned to the user 286 */ 287 packet->PktInfo.AsRx.HTCRxFlags |= 288 HTC_RX_PKT_NO_RECYCLE; 289 } 290 /* add packet to queue (also incase we need to 291 * cleanup down below) 292 */ 293 HTC_PACKET_ENQUEUE(queue, packet); 294 295 /* if (HTC_STOPPING(target)) { 296 * status = QDF_STATUS_E_CANCELED; 297 * break; 298 * } 299 */ 300 301 /* make sure message can fit in the endpoint buffer */ 302 if (full_length > packet->BufferLength) { 303 hif_err("%s: Payload Length Error", __func__); 304 hif_err("%s: header reports payload: %u(%u)", 305 __func__, hdr->PayloadLen, 306 full_length); 307 hif_err("%s: endpoint buffer size: %d\n", 308 __func__, packet->BufferLength); 309 status = QDF_STATUS_E_INVAL; 310 break; 311 } 312 313 if (j > 0) { 314 /* for messages fetched in a bundle the expected 315 * lookahead is unknown as we are only using the 316 * lookahead of the first packet as a template 317 * of what to expect for lengths 318 */ 319 packet->PktInfo.AsRx.HTCRxFlags |= 320 HTC_RX_PKT_REFRESH_HDR; 321 /* set it to something invalid */ 322 packet->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF; 323 } else { 324 packet->PktInfo.AsRx.ExpectedHdr = 325 look_aheads[i]; 326 } 327 /* set the amount of data to fetch */ 328 packet->ActualLength = 329 hdr->PayloadLen + HTC_HDR_LENGTH; 330 if ((j == (num_messages - 1)) && 331 ((hdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK)) 332 packet->PktInfo.AsRx.HTCRxFlags |= 333 HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK; 334 packet->Endpoint = hdr->EndpointID; 335 packet->Completion = NULL; 336 } 337 338 if (QDF_IS_STATUS_ERROR(status)) 339 break; 340 } 341 342 UNLOCK_HIF_DEV_RX(pdev); 343 344 /* for NO RESOURCE error, no need to flush data queue */ 345 if (QDF_IS_STATUS_ERROR(status) && 346 (status != QDF_STATUS_E_RESOURCES)) { 347 while (!HTC_QUEUE_EMPTY(queue)) { 348 qdf_nbuf_t netbuf; 349 350 packet = htc_packet_dequeue(queue); 351 if (!packet) 352 break; 353 netbuf = (qdf_nbuf_t)packet->pNetBufContext; 354 if (netbuf) 355 qdf_nbuf_free(netbuf); 356 } 357 } 358 if (status == QDF_STATUS_E_RESOURCES) 359 status = QDF_STATUS_SUCCESS; 360 return status; 361 } 362 363 /** 364 * hif_dev_process_trailer() - Process the receive frame trailer 365 * @pdev : HIF device object 366 * @buffer : The buffer containing the trailer 367 * @length : Length of the buffer 368 * @next_look_aheads : The lookahead that is next 369 * @num_look_aheads : Number of lookahead information 370 * @from_endpoint : The endpoint on which the trailer is received 371 */ 372 QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev, 373 uint8_t *buffer, int length, 374 uint32_t *next_look_aheads, 375 int *num_look_aheads, 376 HTC_ENDPOINT_ID from_endpoint) 377 { 378 int orig_length; 379 QDF_STATUS status; 380 uint8_t *record_buf; 381 uint8_t *orig_buffer; 382 HTC_RECORD_HDR *record; 383 HTC_LOOKAHEAD_REPORT *look_ahead; 384 385 hif_debug("%s: length:%d", __func__, length); 386 387 orig_buffer = buffer; 388 orig_length = length; 389 status = QDF_STATUS_SUCCESS; 390 391 while (length > 0) { 392 if (length < sizeof(HTC_RECORD_HDR)) { 393 status = QDF_STATUS_E_PROTO; 394 break; 395 } 396 /* these are byte aligned structs */ 397 record = (HTC_RECORD_HDR *)buffer; 398 length -= sizeof(HTC_RECORD_HDR); 399 buffer += sizeof(HTC_RECORD_HDR); 400 401 if (record->Length > length) { 402 /* no room left in buffer for record */ 403 hif_err("%s: invalid record len: (%u, %u)", 404 __func__, record->Length, 405 record->RecordID); 406 hif_err("%s: buffer has %d bytes left", 407 __func__, length); 408 status = QDF_STATUS_E_PROTO; 409 break; 410 } 411 /* start of record follows the header */ 412 record_buf = buffer; 413 414 switch (record->RecordID) { 415 case HTC_RECORD_CREDITS: 416 /* Process in HTC, ignore here */ 417 break; 418 case HTC_RECORD_LOOKAHEAD: 419 A_ASSERT(record->Length >= sizeof(*look_ahead)); 420 look_ahead = (HTC_LOOKAHEAD_REPORT *)record_buf; 421 if ((look_ahead->PreValid == 422 ((~look_ahead->PostValid) & 0xFF)) && 423 next_look_aheads) { 424 hif_debug("%s: look_ahead Report", __func__); 425 hif_debug("%s:prevalid:0x%x, postvalid:0x%x", 426 __func__, look_ahead->PreValid, 427 look_ahead->PostValid); 428 hif_debug("%s:from endpoint %d : %u", 429 __func__, from_endpoint, 430 look_ahead->LookAhead0); 431 /* look ahead bytes are valid, copy them over */ 432 ((uint8_t *)(&next_look_aheads[0]))[0] = 433 look_ahead->LookAhead0; 434 ((uint8_t *)(&next_look_aheads[0]))[1] = 435 look_ahead->LookAhead1; 436 ((uint8_t *)(&next_look_aheads[0]))[2] = 437 look_ahead->LookAhead2; 438 ((uint8_t *)(&next_look_aheads[0]))[3] = 439 look_ahead->LookAhead3; 440 441 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { 442 debug_dump_bytes((uint8_t *) 443 next_look_aheads, 4, 444 "Next Look Ahead"); 445 } 446 /* just one normal lookahead */ 447 if (num_look_aheads) 448 *num_look_aheads = 1; 449 } 450 break; 451 case HTC_RECORD_LOOKAHEAD_BUNDLE: 452 A_ASSERT(record->Length >= 453 sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)); 454 if ((record->Length >= 455 sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)) && 456 next_look_aheads) { 457 HTC_BUNDLED_LOOKAHEAD_REPORT 458 *pBundledLookAheadRpt; 459 int i; 460 461 pBundledLookAheadRpt = 462 (HTC_BUNDLED_LOOKAHEAD_REPORT *)record_buf; 463 464 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { 465 debug_dump_bytes(record_buf, 466 record->Length, 467 "Bundle look_ahead"); 468 } 469 470 if ((record->Length / 471 (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))) 472 > HTC_MAX_MSG_PER_BUNDLE_RX) { 473 /* this should never happen, the target 474 * restricts the number of messages per 475 * bundle configured by the host 476 */ 477 A_ASSERT(false); 478 status = QDF_STATUS_E_PROTO; 479 break; 480 } 481 for (i = 0; 482 i < 483 (int)(record->Length / 484 (sizeof 485 (HTC_BUNDLED_LOOKAHEAD_REPORT))); 486 i++) { 487 ((uint8_t *)(&next_look_aheads[i]))[0] = 488 pBundledLookAheadRpt->LookAhead0; 489 ((uint8_t *)(&next_look_aheads[i]))[1] = 490 pBundledLookAheadRpt->LookAhead1; 491 ((uint8_t *)(&next_look_aheads[i]))[2] = 492 pBundledLookAheadRpt->LookAhead2; 493 ((uint8_t *)(&next_look_aheads[i]))[3] = 494 pBundledLookAheadRpt->LookAhead3; 495 pBundledLookAheadRpt++; 496 } 497 if (num_look_aheads) 498 *num_look_aheads = i; 499 } 500 break; 501 default: 502 hif_err("%s: HIF unhandled record: id:%u length:%u", 503 __func__, record->RecordID, record->Length); 504 break; 505 } 506 507 if (QDF_IS_STATUS_ERROR(status)) 508 break; 509 510 /* advance buffer past this record for next time around */ 511 buffer += record->Length; 512 length -= record->Length; 513 } 514 515 if (QDF_IS_STATUS_ERROR(status)) 516 debug_dump_bytes(orig_buffer, orig_length, 517 "BAD Recv Trailer"); 518 519 hif_debug("%s: status = %d", __func__, status); 520 521 return status; 522 } 523 524 /* process a received message (i.e. strip off header, 525 * process any trailer data). 526 * note : locks must be released when this function is called 527 */ 528 QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev, 529 HTC_PACKET *packet, 530 uint32_t *next_look_aheads, 531 int *num_look_aheads) 532 { 533 uint8_t temp; 534 uint8_t *buf; 535 QDF_STATUS status = QDF_STATUS_SUCCESS; 536 uint16_t payloadLen; 537 uint32_t look_ahead, actual_length; 538 539 buf = packet->pBuffer; 540 actual_length = packet->ActualLength; 541 542 if (num_look_aheads) 543 *num_look_aheads = 0; 544 545 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader\n")); 546 547 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) 548 AR_DEBUG_PRINTBUF(buf, packet->ActualLength, "HTC Recv PKT"); 549 550 do { 551 /* note, we cannot assume the alignment of pBuffer, 552 * so we use the safe macros to 553 * retrieve 16 bit fields 554 */ 555 payloadLen = HTC_GET_FIELD(buf, HTC_FRAME_HDR, 556 PAYLOADLEN); 557 558 ((uint8_t *)&look_ahead)[0] = buf[0]; 559 ((uint8_t *)&look_ahead)[1] = buf[1]; 560 ((uint8_t *)&look_ahead)[2] = buf[2]; 561 ((uint8_t *)&look_ahead)[3] = buf[3]; 562 563 if (packet->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) { 564 /* refresh expected hdr, since this was unknown 565 * at the time we grabbed the packets 566 * as part of a bundle 567 */ 568 packet->PktInfo.AsRx.ExpectedHdr = look_ahead; 569 /* refresh actual length since we now have the 570 * real header 571 */ 572 packet->ActualLength = payloadLen + HTC_HDR_LENGTH; 573 574 /* validate the actual header that was refreshed */ 575 if (packet->ActualLength > packet->BufferLength) { 576 hif_err("%s: Bundled RECV Look ahead: 0x%X", 577 __func__, look_ahead); 578 hif_err("%s: Invalid HDR payload length(%d)", 579 __func__, payloadLen); 580 /* limit this to max buffer just to print out 581 * some of the buffer 582 */ 583 packet->ActualLength = 584 min(packet->ActualLength, 585 packet->BufferLength); 586 status = QDF_STATUS_E_PROTO; 587 break; 588 } 589 590 if (packet->Endpoint 591 != HTC_GET_FIELD(buf, HTC_FRAME_HDR, ENDPOINTID)) { 592 hif_err("%s: Refreshed HDR EP (%d)", 593 __func__, 594 HTC_GET_FIELD(buf, HTC_FRAME_HDR, 595 ENDPOINTID)); 596 hif_err("%s: doesn't match expected EP (%d)", 597 __func__, packet->Endpoint); 598 status = QDF_STATUS_E_PROTO; 599 break; 600 } 601 } 602 603 if (look_ahead != packet->PktInfo.AsRx.ExpectedHdr) { 604 /* somehow the lookahead that gave us the full read 605 * length did not reflect the actual header 606 * in the pending message 607 */ 608 hif_err("%s: lookahead mismatch!", __func__); 609 hif_err("%s: pPkt:0x%lX flags:0x%X", 610 __func__, (unsigned long)packet, 611 packet->PktInfo.AsRx.HTCRxFlags); 612 hif_err("%s: look_ahead 0x%08X != 0x%08X", 613 __func__, look_ahead, 614 packet->PktInfo.AsRx.ExpectedHdr); 615 #ifdef ATH_DEBUG_MODULE 616 debug_dump_bytes((uint8_t *)&packet->PktInfo.AsRx. 617 ExpectedHdr, 4, 618 "Expected Message look_ahead"); 619 debug_dump_bytes(buf, sizeof(HTC_FRAME_HDR), 620 "Current Frame Header"); 621 #ifdef HTC_CAPTURE_LAST_FRAME 622 debug_dump_bytes((uint8_t *)&target->LastFrameHdr, 623 sizeof(HTC_FRAME_HDR), 624 "Last Frame Header"); 625 if (target->LastTrailerLength != 0) 626 debug_dump_bytes(target->LastTrailer, 627 target->LastTrailerLength, 628 "Last trailer"); 629 #endif 630 #endif 631 status = QDF_STATUS_E_PROTO; 632 break; 633 } 634 635 /* get flags */ 636 temp = HTC_GET_FIELD(buf, HTC_FRAME_HDR, FLAGS); 637 638 if (temp & HTC_FLAGS_RECV_TRAILER) { 639 /* this packet has a trailer */ 640 641 /* extract the trailer length in control byte 0 */ 642 temp = HTC_GET_FIELD(buf, HTC_FRAME_HDR, CONTROLBYTES0); 643 644 if ((temp < sizeof(HTC_RECORD_HDR)) || 645 (temp > payloadLen)) { 646 hif_err("%s: invalid header", 647 __func__); 648 hif_err("%s: payloadlength should be :%d", 649 __func__, payloadLen); 650 hif_err("%s: But control bytes is :%d)", 651 __func__, temp); 652 status = QDF_STATUS_E_PROTO; 653 break; 654 } 655 656 if (packet->PktInfo.AsRx. 657 HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) { 658 /* this packet was fetched as part of an HTC 659 * bundle as the lookahead is not valid. 660 * Next packet may have already been fetched as 661 * part of the bundle 662 */ 663 next_look_aheads = NULL; 664 num_look_aheads = NULL; 665 } 666 667 /* process trailer data that follows HDR and 668 * application payload 669 */ 670 status = 671 hif_dev_process_trailer(pdev, 672 (buf + HTC_HDR_LENGTH + 673 payloadLen - temp), 674 temp, 675 next_look_aheads, 676 num_look_aheads, 677 packet->Endpoint); 678 679 if (QDF_IS_STATUS_ERROR(status)) 680 break; 681 } 682 } while (false); 683 684 if (QDF_IS_STATUS_ERROR(status)) { 685 /* dump the whole packet */ 686 debug_dump_bytes(buf, packet->ActualLength, 687 "BAD HTC Recv PKT"); 688 } else { 689 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { 690 if (packet->ActualLength > 0) { 691 AR_DEBUG_PRINTBUF(packet->pBuffer, 692 packet->ActualLength, 693 "HTC - Application Msg"); 694 } 695 } 696 } 697 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, 698 ("-hif_dev_process_recv_header\n")); 699 return status; 700 } 701 702 /** 703 * hif_dev_free_recv_pkt() - Free the allocated recv packets in the queue 704 * @recv_pkt_queue : The queue that contains the packets to be queued 705 * 706 * Return : NONE 707 */ 708 void hif_dev_free_recv_pkt_queue(HTC_PACKET_QUEUE *recv_pkt_queue) 709 { 710 HTC_PACKET *packet; 711 qdf_nbuf_t netbuf; 712 713 while (!HTC_QUEUE_EMPTY(recv_pkt_queue)) { 714 packet = htc_packet_dequeue(recv_pkt_queue); 715 if (!packet) 716 break; 717 netbuf = (qdf_nbuf_t)packet->pNetBufContext; 718 if (netbuf) 719 qdf_nbuf_free(netbuf); 720 } 721 } 722