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