1 /* 2 * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. 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 #include "htc_debug.h" 29 #include "htc_internal.h" 30 #include <qdf_nbuf.h> /* qdf_nbuf_t */ 31 32 /* HTC Control message receive timeout msec */ 33 #define HTC_CONTROL_RX_TIMEOUT 3000 34 35 #if defined(WLAN_DEBUG) || defined(DEBUG) 36 void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription) 37 { 38 int8_t stream[60]; 39 int8_t byteOffsetStr[10]; 40 uint32_t i; 41 uint16_t offset, count, byteOffset; 42 43 A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, 44 pDescription); 45 46 count = 0; 47 offset = 0; 48 byteOffset = 0; 49 for (i = 0; i < length; i++) { 50 A_SNPRINTF(stream + offset, (sizeof(stream) - offset), 51 "%02X ", buffer[i]); 52 count++; 53 offset += 3; 54 55 if (count == 16) { 56 count = 0; 57 offset = 0; 58 A_SNPRINTF(byteOffsetStr, sizeof(byteOffset), "%4.4X", 59 byteOffset); 60 A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); 61 qdf_mem_zero(stream, 60); 62 byteOffset += 16; 63 } 64 } 65 66 if (offset != 0) { 67 A_SNPRINTF(byteOffsetStr, sizeof(byteOffset), "%4.4X", 68 byteOffset); 69 A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); 70 } 71 72 A_PRINTF("<------------------------------------------------->\n"); 73 } 74 #else 75 void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription) 76 { 77 } 78 #endif 79 80 static A_STATUS htc_process_trailer(HTC_TARGET *target, 81 uint8_t *pBuffer, 82 int Length, HTC_ENDPOINT_ID FromEndpoint); 83 84 static void do_recv_completion(HTC_ENDPOINT *pEndpoint, 85 HTC_PACKET_QUEUE *pQueueToIndicate) 86 { 87 88 do { 89 90 if (HTC_QUEUE_EMPTY(pQueueToIndicate)) { 91 /* nothing to indicate */ 92 break; 93 } 94 95 if (pEndpoint->EpCallBacks.EpRecvPktMultiple != NULL) { 96 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, 97 (" HTC calling ep %d, recv multiple callback (%d pkts) \n", 98 pEndpoint->Id, 99 HTC_PACKET_QUEUE_DEPTH 100 (pQueueToIndicate))); 101 /* a recv multiple handler is being used, pass the queue to the handler */ 102 pEndpoint->EpCallBacks.EpRecvPktMultiple(pEndpoint-> 103 EpCallBacks. 104 pContext, 105 pQueueToIndicate); 106 INIT_HTC_PACKET_QUEUE(pQueueToIndicate); 107 } else { 108 HTC_PACKET *pPacket; 109 /* using legacy EpRecv */ 110 while (!HTC_QUEUE_EMPTY(pQueueToIndicate)) { 111 pPacket = htc_packet_dequeue(pQueueToIndicate); 112 if (pEndpoint->EpCallBacks.EpRecv == NULL) { 113 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 114 ("HTC ep %d has NULL recv callback on packet %p\n", 115 pEndpoint->Id, 116 pPacket)); 117 continue; 118 } 119 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, 120 ("HTC calling ep %d recv callback on packet %p\n", 121 pEndpoint->Id, pPacket)); 122 pEndpoint->EpCallBacks.EpRecv(pEndpoint-> 123 EpCallBacks. 124 pContext, 125 pPacket); 126 } 127 } 128 129 } while (false); 130 131 } 132 133 static void recv_packet_completion(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, 134 HTC_PACKET *pPacket) 135 { 136 HTC_PACKET_QUEUE container; 137 INIT_HTC_PACKET_QUEUE_AND_ADD(&container, pPacket); 138 /* do completion */ 139 do_recv_completion(pEndpoint, &container); 140 } 141 142 void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket) 143 { 144 /* TODO, can't really receive HTC control messages yet.... */ 145 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 146 ("Invalid call to htc_control_rx_complete\n")); 147 } 148 149 void htc_unblock_recv(HTC_HANDLE HTCHandle) 150 { 151 /* TODO find the Need in new model */ 152 } 153 154 void htc_enable_recv(HTC_HANDLE HTCHandle) 155 { 156 157 /* TODO find the Need in new model */ 158 } 159 160 void htc_disable_recv(HTC_HANDLE HTCHandle) 161 { 162 163 /* TODO find the Need in new model */ 164 } 165 166 int htc_get_num_recv_buffers(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint) 167 { 168 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 169 HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint]; 170 return HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBufferHoldQueue); 171 } 172 173 HTC_PACKET *allocate_htc_packet_container(HTC_TARGET *target) 174 { 175 HTC_PACKET *pPacket; 176 177 LOCK_HTC_RX(target); 178 179 if (NULL == target->pHTCPacketStructPool) { 180 UNLOCK_HTC_RX(target); 181 return NULL; 182 } 183 184 pPacket = target->pHTCPacketStructPool; 185 target->pHTCPacketStructPool = (HTC_PACKET *) pPacket->ListLink.pNext; 186 187 UNLOCK_HTC_RX(target); 188 189 pPacket->ListLink.pNext = NULL; 190 return pPacket; 191 } 192 193 void free_htc_packet_container(HTC_TARGET *target, HTC_PACKET *pPacket) 194 { 195 LOCK_HTC_RX(target); 196 197 if (NULL == target->pHTCPacketStructPool) { 198 target->pHTCPacketStructPool = pPacket; 199 pPacket->ListLink.pNext = NULL; 200 } else { 201 pPacket->ListLink.pNext = 202 (DL_LIST *) target->pHTCPacketStructPool; 203 target->pHTCPacketStructPool = pPacket; 204 } 205 206 UNLOCK_HTC_RX(target); 207 } 208 209 #ifdef RX_SG_SUPPORT 210 qdf_nbuf_t rx_sg_to_single_netbuf(HTC_TARGET *target) 211 { 212 qdf_nbuf_t skb; 213 uint8_t *anbdata; 214 uint8_t *anbdata_new; 215 uint32_t anblen; 216 qdf_nbuf_t new_skb = NULL; 217 uint32_t sg_queue_len; 218 qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; 219 220 sg_queue_len = qdf_nbuf_queue_len(rx_sg_queue); 221 222 if (sg_queue_len <= 1) { 223 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 224 ("rx_sg_to_single_netbuf: invalid sg queue len %u\n")); 225 goto _failed; 226 } 227 228 new_skb = qdf_nbuf_alloc(target->ExpRxSgTotalLen, 0, 4, false); 229 if (new_skb == NULL) { 230 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 231 ("rx_sg_to_single_netbuf: can't allocate %u size netbuf\n", 232 target->ExpRxSgTotalLen)); 233 goto _failed; 234 } 235 236 qdf_nbuf_peek_header(new_skb, &anbdata_new, &anblen); 237 238 skb = qdf_nbuf_queue_remove(rx_sg_queue); 239 do { 240 qdf_nbuf_peek_header(skb, &anbdata, &anblen); 241 qdf_mem_copy(anbdata_new, anbdata, qdf_nbuf_len(skb)); 242 qdf_nbuf_put_tail(new_skb, qdf_nbuf_len(skb)); 243 anbdata_new += qdf_nbuf_len(skb); 244 qdf_nbuf_free(skb); 245 skb = qdf_nbuf_queue_remove(rx_sg_queue); 246 } while (skb != NULL); 247 248 RESET_RX_SG_CONFIG(target); 249 return new_skb; 250 251 _failed: 252 253 while ((skb = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL) 254 qdf_nbuf_free(skb); 255 256 RESET_RX_SG_CONFIG(target); 257 return NULL; 258 } 259 #endif 260 261 #ifdef CONFIG_WIN 262 #define HTC_MSG_NACK_SUSPEND 7 263 #endif 264 265 QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf, 266 uint8_t pipeID) 267 { 268 QDF_STATUS status = QDF_STATUS_SUCCESS; 269 HTC_FRAME_HDR *HtcHdr; 270 HTC_TARGET *target = (HTC_TARGET *) Context; 271 uint8_t *netdata; 272 uint32_t netlen; 273 HTC_ENDPOINT *pEndpoint; 274 HTC_PACKET *pPacket; 275 uint16_t payloadLen; 276 uint32_t trailerlen = 0; 277 uint8_t htc_ep_id; 278 HTC_INIT_INFO *info; 279 280 #ifdef RX_SG_SUPPORT 281 LOCK_HTC_RX(target); 282 if (target->IsRxSgInprogress) { 283 target->CurRxSgTotalLen += qdf_nbuf_len(netbuf); 284 qdf_nbuf_queue_add(&target->RxSgQueue, netbuf); 285 if (target->CurRxSgTotalLen == target->ExpRxSgTotalLen) { 286 netbuf = rx_sg_to_single_netbuf(target); 287 if (netbuf == NULL) { 288 UNLOCK_HTC_RX(target); 289 goto _out; 290 } 291 } else { 292 netbuf = NULL; 293 UNLOCK_HTC_RX(target); 294 goto _out; 295 } 296 } 297 UNLOCK_HTC_RX(target); 298 #endif 299 300 netdata = qdf_nbuf_data(netbuf); 301 netlen = qdf_nbuf_len(netbuf); 302 303 HtcHdr = (HTC_FRAME_HDR *) netdata; 304 305 do { 306 307 htc_ep_id = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, ENDPOINTID); 308 309 if (htc_ep_id >= ENDPOINT_MAX) { 310 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 311 ("HTC Rx: invalid EndpointID=%d\n", 312 htc_ep_id)); 313 debug_dump_bytes((uint8_t *) HtcHdr, 314 sizeof(HTC_FRAME_HDR), "BAD HTC Header"); 315 status = QDF_STATUS_E_FAILURE; 316 QDF_BUG(0); 317 break; 318 } 319 320 pEndpoint = &target->endpoint[htc_ep_id]; 321 322 /* 323 * If this endpoint that received a message from the target has 324 * a to-target HIF pipe whose send completions are polled rather 325 * than interrupt-driven, this is a good point to ask HIF to check 326 * whether it has any completed sends to handle. 327 */ 328 if (pEndpoint->ul_is_polled) { 329 htc_send_complete_check(pEndpoint, 1); 330 } 331 332 payloadLen = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, PAYLOADLEN); 333 334 if (netlen < (payloadLen + HTC_HDR_LENGTH)) { 335 #ifdef RX_SG_SUPPORT 336 LOCK_HTC_RX(target); 337 target->IsRxSgInprogress = true; 338 qdf_nbuf_queue_init(&target->RxSgQueue); 339 qdf_nbuf_queue_add(&target->RxSgQueue, netbuf); 340 target->ExpRxSgTotalLen = (payloadLen + HTC_HDR_LENGTH); 341 target->CurRxSgTotalLen += netlen; 342 UNLOCK_HTC_RX(target); 343 netbuf = NULL; 344 break; 345 #else 346 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 347 ("HTC Rx: insufficient length, got:%d expected =%zu\n", 348 netlen, payloadLen + HTC_HDR_LENGTH)); 349 debug_dump_bytes((uint8_t *) HtcHdr, 350 sizeof(HTC_FRAME_HDR), 351 "BAD RX packet length"); 352 status = QDF_STATUS_E_FAILURE; 353 QDF_BUG(0); 354 break; 355 #endif 356 } 357 #ifdef HTC_EP_STAT_PROFILING 358 LOCK_HTC_RX(target); 359 INC_HTC_EP_STAT(pEndpoint, RxReceived, 1); 360 UNLOCK_HTC_RX(target); 361 #endif 362 363 /* if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { */ 364 { 365 uint8_t temp; 366 A_STATUS temp_status; 367 /* get flags to check for trailer */ 368 temp = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, FLAGS); 369 if (temp & HTC_FLAGS_RECV_TRAILER) { 370 /* extract the trailer length */ 371 temp = 372 HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, 373 CONTROLBYTES0); 374 if ((temp < sizeof(HTC_RECORD_HDR)) 375 || (temp > payloadLen)) { 376 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 377 ("htc_rx_completion_handler, invalid header (payloadlength should be :%d, CB[0] is:%d)\n", 378 payloadLen, temp)); 379 status = QDF_STATUS_E_INVAL; 380 break; 381 } 382 383 trailerlen = temp; 384 /* process trailer data that follows HDR + application payload */ 385 temp_status = htc_process_trailer(target, 386 ((uint8_t *) HtcHdr + 387 HTC_HDR_LENGTH + 388 payloadLen - temp), 389 temp, htc_ep_id); 390 if (A_FAILED(temp_status)) { 391 status = QDF_STATUS_E_FAILURE; 392 break; 393 } 394 395 } 396 } 397 398 if (((int)payloadLen - (int)trailerlen) <= 0) { 399 /* zero length packet with trailer data, just drop these */ 400 break; 401 } 402 403 if (htc_ep_id == ENDPOINT_0) { 404 uint16_t message_id; 405 HTC_UNKNOWN_MSG *htc_msg; 406 bool wow_nack; 407 408 /* remove HTC header */ 409 qdf_nbuf_pull_head(netbuf, HTC_HDR_LENGTH); 410 netdata = qdf_nbuf_data(netbuf); 411 netlen = qdf_nbuf_len(netbuf); 412 413 htc_msg = (HTC_UNKNOWN_MSG *) netdata; 414 message_id = 415 HTC_GET_FIELD(htc_msg, HTC_UNKNOWN_MSG, MESSAGEID); 416 417 switch (message_id) { 418 default: 419 /* handle HTC control message */ 420 if (target->CtrlResponseProcessing) { 421 /* this is a fatal error, target should not be sending unsolicited messages 422 * on the endpoint 0 */ 423 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 424 ("HTC Rx Ctrl still processing\n")); 425 status = QDF_STATUS_E_FAILURE; 426 QDF_BUG(false); 427 break; 428 } 429 430 LOCK_HTC_RX(target); 431 target->CtrlResponseLength = 432 min((int)netlen, 433 HTC_MAX_CONTROL_MESSAGE_LENGTH); 434 qdf_mem_copy(target->CtrlResponseBuffer, 435 netdata, 436 target->CtrlResponseLength); 437 438 /* Requester will clear this flag */ 439 target->CtrlResponseProcessing = true; 440 UNLOCK_HTC_RX(target); 441 442 qdf_event_set(&target->ctrl_response_valid); 443 break; 444 #ifdef HTC_MSG_WAKEUP_FROM_SUSPEND_ID 445 case HTC_MSG_WAKEUP_FROM_SUSPEND_ID: 446 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 447 ("Received initial wake up")); 448 LOCK_HTC_CREDIT(target); 449 htc_credit_record(HTC_INITIAL_WAKE_UP, 450 pEndpoint->TxCredits, 451 HTC_PACKET_QUEUE_DEPTH( 452 &pEndpoint->TxQueue)); 453 UNLOCK_HTC_CREDIT(target); 454 info = &target->HTCInitInfo; 455 if (info && info->target_initial_wakeup_cb) 456 info->target_initial_wakeup_cb( 457 info->target_psoc); 458 else 459 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 460 ("No initial wake up cb")); 461 break; 462 #endif 463 case HTC_MSG_SEND_SUSPEND_COMPLETE: 464 wow_nack = false; 465 LOCK_HTC_CREDIT(target); 466 htc_credit_record(HTC_SUSPEND_ACK, 467 pEndpoint->TxCredits, 468 HTC_PACKET_QUEUE_DEPTH( 469 &pEndpoint->TxQueue)); 470 UNLOCK_HTC_CREDIT(target); 471 target->HTCInitInfo.TargetSendSuspendComplete( 472 target->HTCInitInfo.target_psoc, 473 wow_nack); 474 475 break; 476 case HTC_MSG_NACK_SUSPEND: 477 wow_nack = true; 478 LOCK_HTC_CREDIT(target); 479 htc_credit_record(HTC_SUSPEND_ACK, 480 pEndpoint->TxCredits, 481 HTC_PACKET_QUEUE_DEPTH( 482 &pEndpoint->TxQueue)); 483 UNLOCK_HTC_CREDIT(target); 484 485 target->HTCInitInfo.TargetSendSuspendComplete( 486 target->HTCInitInfo.target_psoc, 487 wow_nack); 488 break; 489 } 490 491 qdf_nbuf_free(netbuf); 492 netbuf = NULL; 493 break; 494 } 495 496 /* the current message based HIF architecture allocates net bufs for recv packets 497 * since this layer bridges that HIF to upper layers , which expects HTC packets, 498 * we form the packets here 499 * TODO_FIXME */ 500 pPacket = allocate_htc_packet_container(target); 501 if (NULL == pPacket) { 502 status = QDF_STATUS_E_RESOURCES; 503 break; 504 } 505 pPacket->Status = QDF_STATUS_SUCCESS; 506 pPacket->Endpoint = htc_ep_id; 507 pPacket->pPktContext = netbuf; 508 pPacket->pBuffer = qdf_nbuf_data(netbuf) + HTC_HDR_LENGTH; 509 pPacket->ActualLength = netlen - HTC_HEADER_LEN - trailerlen; 510 511 qdf_nbuf_pull_head(netbuf, HTC_HEADER_LEN); 512 qdf_nbuf_set_pktlen(netbuf, pPacket->ActualLength); 513 514 recv_packet_completion(target, pEndpoint, pPacket); 515 /* recover the packet container */ 516 free_htc_packet_container(target, pPacket); 517 netbuf = NULL; 518 519 } while (false); 520 521 #ifdef RX_SG_SUPPORT 522 _out: 523 #endif 524 525 if (netbuf != NULL) { 526 qdf_nbuf_free(netbuf); 527 } 528 529 return status; 530 531 } 532 533 A_STATUS htc_add_receive_pkt_multiple(HTC_HANDLE HTCHandle, 534 HTC_PACKET_QUEUE *pPktQueue) 535 { 536 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 537 HTC_ENDPOINT *pEndpoint; 538 HTC_PACKET *pFirstPacket; 539 A_STATUS status = A_OK; 540 HTC_PACKET *pPacket; 541 542 pFirstPacket = htc_get_pkt_at_head(pPktQueue); 543 544 if (NULL == pFirstPacket) { 545 A_ASSERT(false); 546 return A_EINVAL; 547 } 548 549 AR_DEBUG_ASSERT(pFirstPacket->Endpoint < ENDPOINT_MAX); 550 551 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, 552 ("+- htc_add_receive_pkt_multiple : endPointId: %d, cnt:%d, length: %d\n", 553 pFirstPacket->Endpoint, 554 HTC_PACKET_QUEUE_DEPTH(pPktQueue), 555 pFirstPacket->BufferLength)); 556 557 pEndpoint = &target->endpoint[pFirstPacket->Endpoint]; 558 559 LOCK_HTC_RX(target); 560 561 do { 562 563 if (HTC_STOPPING(target)) { 564 status = A_ERROR; 565 break; 566 } 567 568 /* store receive packets */ 569 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBufferHoldQueue, 570 pPktQueue); 571 572 } while (false); 573 574 UNLOCK_HTC_RX(target); 575 576 if (A_FAILED(status)) { 577 /* walk through queue and mark each one canceled */ 578 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue, pPacket) { 579 pPacket->Status = A_ECANCELED; 580 } 581 HTC_PACKET_QUEUE_ITERATE_END; 582 583 do_recv_completion(pEndpoint, pPktQueue); 584 } 585 586 return status; 587 } 588 589 A_STATUS htc_add_receive_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) 590 { 591 HTC_PACKET_QUEUE queue; 592 INIT_HTC_PACKET_QUEUE_AND_ADD(&queue, pPacket); 593 return htc_add_receive_pkt_multiple(HTCHandle, &queue); 594 } 595 596 void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint) 597 { 598 HTC_PACKET *pPacket; 599 HTC_PACKET_QUEUE container; 600 601 LOCK_HTC_RX(target); 602 603 while (1) { 604 pPacket = htc_packet_dequeue(&pEndpoint->RxBufferHoldQueue); 605 if (NULL == pPacket) { 606 break; 607 } 608 UNLOCK_HTC_RX(target); 609 pPacket->Status = A_ECANCELED; 610 pPacket->ActualLength = 0; 611 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, 612 (" Flushing RX packet:%p, length:%d, ep:%d \n", 613 pPacket, pPacket->BufferLength, 614 pPacket->Endpoint)); 615 INIT_HTC_PACKET_QUEUE_AND_ADD(&container, pPacket); 616 /* give the packet back */ 617 do_recv_completion(pEndpoint, &container); 618 LOCK_HTC_RX(target); 619 } 620 621 UNLOCK_HTC_RX(target); 622 } 623 624 void htc_recv_init(HTC_TARGET *target) 625 { 626 /* Initialize ctrl_response_valid to block */ 627 qdf_event_create(&target->ctrl_response_valid); 628 } 629 630 /* polling routine to wait for a control packet to be received */ 631 A_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target) 632 { 633 /* int count = HTC_TARGET_MAX_RESPONSE_POLL; */ 634 635 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCWaitCtrlMessageRecv\n")); 636 637 /* Wait for BMI request/response transaction to complete */ 638 if (qdf_wait_single_event(&target->ctrl_response_valid, 639 HTC_CONTROL_RX_TIMEOUT)) { 640 QDF_BUG(0); 641 return A_ERROR; 642 } 643 644 LOCK_HTC_RX(target); 645 /* caller will clear this flag */ 646 target->CtrlResponseProcessing = true; 647 648 UNLOCK_HTC_RX(target); 649 650 #if 0 651 while (count > 0) { 652 653 LOCK_HTC_RX(target); 654 655 if (target->CtrlResponseValid) { 656 target->CtrlResponseValid = false; 657 /* caller will clear this flag */ 658 target->CtrlResponseProcessing = true; 659 UNLOCK_HTC_RX(target); 660 break; 661 } 662 663 UNLOCK_HTC_RX(target); 664 665 count--; 666 A_MSLEEP(HTC_TARGET_RESPONSE_POLL_MS); 667 } 668 669 if (count <= 0) { 670 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 671 ("-HTCWaitCtrlMessageRecv: Timeout!\n")); 672 return A_ECOMM; 673 } 674 #endif 675 676 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCWaitCtrlMessageRecv success\n")); 677 return A_OK; 678 } 679 680 static A_STATUS htc_process_trailer(HTC_TARGET *target, 681 uint8_t *pBuffer, 682 int Length, HTC_ENDPOINT_ID FromEndpoint) 683 { 684 HTC_RECORD_HDR *pRecord; 685 uint8_t htc_rec_id; 686 uint8_t htc_rec_len; 687 uint8_t *pRecordBuf; 688 uint8_t *pOrigBuffer; 689 int origLength; 690 A_STATUS status; 691 692 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, 693 ("+htc_process_trailer (length:%d) \n", Length)); 694 695 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { 696 AR_DEBUG_PRINTBUF(pBuffer, Length, "Recv Trailer"); 697 } 698 699 pOrigBuffer = pBuffer; 700 origLength = Length; 701 status = A_OK; 702 703 while (Length > 0) { 704 705 if (Length < sizeof(HTC_RECORD_HDR)) { 706 status = A_EPROTO; 707 break; 708 } 709 /* these are byte aligned structs */ 710 pRecord = (HTC_RECORD_HDR *) pBuffer; 711 Length -= sizeof(HTC_RECORD_HDR); 712 pBuffer += sizeof(HTC_RECORD_HDR); 713 714 htc_rec_len = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, LENGTH); 715 htc_rec_id = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, RECORDID); 716 717 if (htc_rec_len > Length) { 718 /* no room left in buffer for record */ 719 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 720 (" invalid record length: %d (id:%d) buffer has: %d bytes left \n", 721 htc_rec_len, htc_rec_id, Length)); 722 status = A_EPROTO; 723 break; 724 } 725 /* start of record follows the header */ 726 pRecordBuf = pBuffer; 727 728 switch (htc_rec_id) { 729 case HTC_RECORD_CREDITS: 730 AR_DEBUG_ASSERT(htc_rec_len >= 731 sizeof(HTC_CREDIT_REPORT)); 732 htc_process_credit_rpt(target, 733 (HTC_CREDIT_REPORT *) pRecordBuf, 734 htc_rec_len / 735 (sizeof(HTC_CREDIT_REPORT)), 736 FromEndpoint); 737 break; 738 739 #ifdef HIF_SDIO 740 case HTC_RECORD_LOOKAHEAD: 741 /* Process in HIF layer */ 742 break; 743 744 case HTC_RECORD_LOOKAHEAD_BUNDLE: 745 /* Process in HIF layer */ 746 break; 747 #endif /* HIF_SDIO */ 748 749 default: 750 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 751 (" HTC unhandled record: id:%d length:%d \n", 752 htc_rec_id, htc_rec_len)); 753 break; 754 } 755 756 if (A_FAILED(status)) { 757 break; 758 } 759 760 /* advance buffer past this record for next time around */ 761 pBuffer += htc_rec_len; 762 Length -= htc_rec_len; 763 } 764 765 if (A_FAILED(status)) { 766 debug_dump_bytes(pOrigBuffer, origLength, "BAD Recv Trailer"); 767 } 768 769 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-htc_process_trailer \n")); 770 return status; 771 772 } 773