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