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